From 278c8a6d1f0518dc9d0875dbec84614b19800d5d Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 7 Jan 2021 20:03:54 +0100 Subject: switch from custom monitoring to Spring-Actuator healthchecks --- connector/pom.xml | 5 + .../connector/controller/MonitoringController.java | 279 --------------------- .../health/EidasNodeMetadataHealthIndicator.java | 69 +++++ .../health/Saml2MetadataHealthIndicator.java | 44 ++++ .../tasks/GenerateCountrySelectionFrameTask.java | 11 +- .../EidasCacheTransactionStoreDecorator.java | 32 ++- .../main/resources/SpringTest_connector.beans.xml | 129 ---------- .../resources/specific_eIDAS_connector.beans.xml | 7 +- .../test/MainClassExecutableModeTest.java | 14 +- .../connector/test/MainClassWebAppModeTest.java | 11 +- ...sNodeMetadataHealthIndicatorNoEndpointTest.java | 70 ++++++ .../EidasNodeMetadataHealthIndicatorTest.java | 102 ++++++++ .../test/utils/AuthenticationDataBuilderTest.java | 2 +- .../config/junit_config_1_springboot.properties | 2 +- .../config/junit_config_2_springboot.properties | 83 ++++++ .../spring/SpringTest-context_healthcheck.xml | 22 ++ .../spring/SpringTest_connector.beans.xml | 122 +++++++++ .../specific/modules/auth/eidas/v2/Constants.java | 6 +- .../EidasRequestPreProcessingFirstTest.java | 8 +- .../config/junit_config_de_attributes.properties | 2 + pom.xml | 8 +- 21 files changed, 589 insertions(+), 439 deletions(-) delete mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java delete mode 100644 connector/src/main/resources/SpringTest_connector.beans.xml create mode 100644 connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java create mode 100644 connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java create mode 100644 connector/src/test/resources/config/junit_config_2_springboot.properties create mode 100644 connector/src/test/resources/spring/SpringTest-context_healthcheck.xml create mode 100644 connector/src/test/resources/spring/SpringTest_connector.beans.xml diff --git a/connector/pom.xml b/connector/pom.xml index 03492a5d..2484e542 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -148,6 +148,11 @@ 2.0.7 test + + com.squareup.okhttp3 + mockwebserver + test + diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java deleted file mode 100644 index f2d9fc8c..00000000 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2018 A-SIT Plus GmbH - * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, - * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "License"); - * You may not use this work except in compliance with the License. - * You may obtain a copy of the License at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.asitplus.eidas.specific.connector.controller; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.TransformerFactoryConfigurationError; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - -@Controller -public class MonitoringController { - private static final Logger log = LoggerFactory.getLogger(MonitoringController.class); - - private static final String MESSAGE_OK = "OK"; - private static final String MESSAGE_ERROR = "ERROR"; - private static final String MESSAGE_SKIPPED = "SKIPPED"; - - private static final String TEST_STORAGE = "Storage: "; - private static final String TEST_CONFIG = "Config: "; - private static final String TEST_PVPMETADATA = "PVP_metadata: "; - private static final String TEST_EIDASNODEMETADATA = "eIDASNode_metadata: "; - - @Autowired - private ITransactionStorage storage; - @Autowired - private IConfigurationWithSP config; - - @Autowired private IHttpClientFactory httpClientFactory; - - @Autowired - private PvpMetadataBuilder metadatabuilder; - @Autowired - private IPvpMetadataConfigurationFactory configFactory; - private AbstractCredentialProvider pvpIdpCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * - * @param pvpIdpCredentials credential provider - */ - public void setPvpIdpCredentials(AbstractCredentialProvider pvpIdpCredentials) { - this.pvpIdpCredentials = pvpIdpCredentials; - - } - - /** - * Generic exception handling that wrote an error-message to html response. - * - * @param resp Http response object - * @param exception Error - * @throws IOException In case of a html response error. - */ - @ExceptionHandler({ Throwable.class }) - public void genericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { - log.error("Monitoring Servlet receives an error.", exception); - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write("Reason: " - + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage()))); - - } - - /** - * MS-Connector status-monitoring end-point. - * - * @param req http request - * @param resp http response - * @throws IOException In case of a general processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_MONITOR }, - method = { RequestMethod.GET }) - public void startFullTest(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - - try { - testConfig(); - testStorage(); - testPvpMetadata(); - testEidasNodeMetadata(); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(MESSAGE_OK); - - } catch (final Exception e) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write(MESSAGE_ERROR); - - } - - } - - /** - * MS-Connector internal verify monitoring end-point. - * - * @param req http request object - * @param resp http response object - * @throws IOException In case of an internal processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_VERIFY }, - method = { RequestMethod.GET }) - - public void startSingleTests(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String result = StringUtils.EMPTY; - try { - result += testConfig() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testStorage() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testPvpMetadata() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testEidasNodeMetadata() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(result); - - } - - private String testStorage() throws Exception { - try { - final String key = Random.nextHexRandom16(); - final String value = Random.nextHexRandom16(); - - storage.put(key, value, -1); - final String result = storage.get(key, String.class); - storage.remove(key); - - if (result != null && result.equals(value)) { - return TEST_STORAGE + MESSAGE_OK; - } else { - log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); - } - - } catch (final EaafException e) { - log.warn("Montioring: Can not read/write to storage.", e); - - } - - throw new Exception(TEST_STORAGE + MESSAGE_ERROR); - - } - - private String testConfig() throws Exception { - try { - if (config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) != null - && config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) - .size() > 0) { - return TEST_CONFIG + MESSAGE_OK; - } else { - log.warn("Montioring: Can not read from configuration file."); - } - - } catch (final Exception e) { - log.warn("Montioring: Can not read from configuration file.", e); - } - - throw new Exception(TEST_CONFIG + MESSAGE_ERROR); - - } - - private String testPvpMetadata() throws Exception { - try { - // build metadata - final IPvpMetadataBuilderConfiguration metadataConfig = - configFactory.generateMetadataBuilderConfiguration( - "http://localhost/monitoring", - pvpIdpCredentials); - metadatabuilder.buildPvpMetadata(metadataConfig); - return TEST_PVPMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_PVPMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_PVPMETADATA + MESSAGE_ERROR, e); - - } - - } - - private String testEidasNodeMetadata() throws Exception { - try { - final String urlString = config.getBasicConfiguration( - MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); - if (StringUtils.isEmpty(urlString)) { - log.debug("No eIDASNode metadata URL. Skipping test ... "); - return TEST_EIDASNODEMETADATA + MESSAGE_SKIPPED; - - } - - // create HTTP client - CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); - URIBuilder uriBuilder = new URIBuilder(urlString); - HttpUriRequest request = new HttpGet(uriBuilder.build()); - - final CloseableHttpResponse respCode = httpClient.execute(request); - if (respCode.getStatusLine().getStatusCode() != 200) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + " HTTP responsecode: " - + respCode); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR); - - } - - // parse metadata - DomUtils.parseXmlNonValidating(respCode.getEntity().getContent()); - - return TEST_EIDASNODEMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR, e); - - } - - } - -} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java new file mode 100644 index 00000000..f160916c --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java @@ -0,0 +1,69 @@ +package at.asitplus.eidas.specific.connector.health; + +import java.io.ByteArrayInputStream; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Triple; +import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EidasNodeMetadataHealthIndicator implements HealthIndicator { + + @Autowired IConfiguration config; + @Autowired IHttpClientFactory httpClientFactory; + + @Override + public Health health() { + try { + final String urlString = config.getBasicConfiguration( + MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); + if (StringUtils.isEmpty(urlString)) { + log.trace("No eIDASNode metadata URL. Skipping test ... "); + return Health.unknown().build(); + + } + + // create HTTP client + CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); + URIBuilder uriBuilder = new URIBuilder(urlString); + HttpUriRequest request = new HttpGet(uriBuilder.build()); + + final Triple respCode = httpClient.execute(request, + HttpUtils.bodyStatusCodeResponseHandler()); + if (respCode.getFirst().getStatusCode() != 200) { + log.warn("Monitoring: Get http StatusCode: {} from eIDAS-Node Metadata endpoint", + respCode.getFirst().getStatusCode()); + return Health.down().withDetail("http StatusCode", respCode.getFirst().getStatusCode()).build(); + + } + + // parse metadata + DomUtils.parseXmlNonValidating(respCode.getSecond()); + + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + log.warn("Monitoring: Can not read SAML2 metadata from eIDAS-Node", e); + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java new file mode 100644 index 00000000..592231b0 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java @@ -0,0 +1,44 @@ +package at.asitplus.eidas.specific.connector.health; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class Saml2MetadataHealthIndicator implements HealthIndicator { + + @Autowired + private PvpMetadataBuilder metadatabuilder; + @Autowired + private IPvpMetadataConfigurationFactory configFactory; + + @Setter + private AbstractCredentialProvider pvpIdpCredentials; + + @Override + public Health health() { + try { + // build metadata + final IPvpMetadataBuilderConfiguration metadataConfig = + configFactory.generateMetadataBuilderConfiguration( + "http://localhost/monitoring", + pvpIdpCredentials); + metadatabuilder.buildPvpMetadata(metadataConfig); + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java index 86808f01..d3b8116a 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java @@ -26,8 +26,6 @@ package at.asitplus.eidas.specific.connector.processes.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -39,7 +37,6 @@ import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -51,7 +48,6 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; */ @Component("GenerateCountrySelectionFrameTask") public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(GenerateCountrySelectionFrameTask.class); @Autowired ISpringMvcGuiFormBuilder guiBuilder; @@ -77,16 +73,11 @@ public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { guiBuilder.build(request, response, config, "BKU-Selection form"); - } catch (final GuiBuildException e) { - log.warn("Can not build GUI:'BKU-Selection'. Msg:" + e.getMessage()); + } catch (final Exception e) { throw new TaskExecutionException(pendingReq, "Can not build GUI. Msg:" + e.getMessage(), new EaafException("gui.00", new Object[] { e.getMessage() }, e)); - } catch (final Exception e) { - log.warn("FinalizeAuthenticationTask has an internal error", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java index 557e245a..1ea5a280 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java @@ -30,17 +30,46 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.utils.Random; -public class EidasCacheTransactionStoreDecorator implements ITransactionStorage { +public class EidasCacheTransactionStoreDecorator implements ITransactionStorage, HealthIndicator { private static final Logger log = LoggerFactory.getLogger(EidasCacheTransactionStoreDecorator.class); @Autowired(required = true) private CacheWithEidasBackend storage; + @Override + public Health health() { + try { + final String key = Random.nextHexRandom16(); + final String value = Random.nextHexRandom16(); + + this.put(key, value, -1); + final String result = this.get(key, String.class); + this.remove(key); + + if (result != null && result.equals(value)) { + return Health.up().build(); + + } else { + log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); + return Health.down().build(); + + } + + } catch (final EaafException e) { + log.warn("Montioring: Can not read/write to storage.", e); + return Health.down().down(e).build(); + + } + } + @Override public void changeKey(String oldKey, String newKey, Object value) throws EaafException { if (containsKey(oldKey)) { @@ -148,5 +177,4 @@ public class EidasCacheTransactionStoreDecorator implements ITransactionStorage } } - } diff --git a/connector/src/main/resources/SpringTest_connector.beans.xml b/connector/src/main/resources/SpringTest_connector.beans.xml deleted file mode 100644 index 5cf0d5b8..00000000 --- a/connector/src/main/resources/SpringTest_connector.beans.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/connector/src/main/resources/specific_eIDAS_connector.beans.xml b/connector/src/main/resources/specific_eIDAS_connector.beans.xml index aa5040fa..f6fdeefe 100644 --- a/connector/src/main/resources/specific_eIDAS_connector.beans.xml +++ b/connector/src/main/resources/specific_eIDAS_connector.beans.xml @@ -19,13 +19,16 @@ - + + + diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java index a865c8bd..9f4088f2 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java @@ -84,7 +84,7 @@ public class MainClassExecutableModeTest { public void validConfigLocation() throws Throwable { SpringBootApplicationInitializer .main(new String[] { - "--spring.config.location=src/test/resources/config/junit_config_1_springboot.properties,classpath:/application.properties", + "--spring.config.location=src/test/resources/config/junit_config_2_springboot.properties,classpath:/application.properties", "--spring.profiles.active=jUnitTestMode" }); System.out.println("Is started!"); @@ -100,10 +100,14 @@ public class MainClassExecutableModeTest { final CloseableHttpClient client = builder.build(); Assert.assertNotNull("httpClient", client); - final HttpUriRequest httpGet1 = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); - final CloseableHttpResponse httpResp1 = client.execute(httpGet1); - Assert.assertEquals("http statusCode", 200, httpResp1.getStatusLine().getStatusCode()); - + final HttpUriRequest httpGetInfo = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); + final CloseableHttpResponse httpRespInfo = client.execute(httpGetInfo); + Assert.assertEquals("http statusCode", 200, httpRespInfo.getStatusLine().getStatusCode()); + + final HttpUriRequest httpGetHealth = new HttpGet("http://localhost:8080/ms_connector/actuator/health"); + final CloseableHttpResponse httpRespHealth = client.execute(httpGetHealth); + Assert.assertEquals("http statusCode", 200, httpRespHealth.getStatusLine().getStatusCode()); + } } diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java index c390184b..07ef4968 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java @@ -120,10 +120,15 @@ public class MainClassWebAppModeTest { final CloseableHttpClient client = builder.build(); Assert.assertNotNull("httpClient", client); - final HttpUriRequest httpGet1 = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); - final CloseableHttpResponse httpResp1 = client.execute(httpGet1); - Assert.assertEquals("http statusCode", 200, httpResp1.getStatusLine().getStatusCode()); + final HttpUriRequest httpGetInfo = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); + final CloseableHttpResponse httpRespInfo = client.execute(httpGetInfo); + Assert.assertEquals("http statusCode", 200, httpRespInfo.getStatusLine().getStatusCode()); + + final HttpUriRequest httpGetHealth = new HttpGet("http://localhost:8080/ms_connector/actuator/health"); + final CloseableHttpResponse httpRespHealth = client.execute(httpGetHealth); + Assert.assertEquals("http statusCode", 503, httpRespHealth.getStatusLine().getStatusCode()); + } } diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java new file mode 100644 index 00000000..b04a5bdb --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java @@ -0,0 +1,70 @@ +package at.asitplus.eidas.specific.connector.test.health; + +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/spring/SpringTest-context_healthcheck.xml" }) +@TestPropertySource(locations = {"classpath:/config/junit_config_2_springboot.properties"}) +@WebAppConfiguration +public class EidasNodeMetadataHealthIndicatorNoEndpointTest { + + @Autowired EidasNodeMetadataHealthIndicator health; + + private static MockWebServer mockWebServer = null; + + /** + * Testclass initializer. + * + * @throws IOException In case of an error + */ + @BeforeClass + public static void classInitializer() throws IOException { + mockWebServer = new MockWebServer(); + mockWebServer.start(40900); + mockWebServer.url("/mockup"); + + } + + @AfterClass + public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException, IOException { + mockWebServer.shutdown(); + + } + + @Test + public void noEndpointInConfiguration() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorNoEndpointTest.class + .getResourceAsStream("/config/log4j.properties"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.unknown().build().getStatus(), status.getStatus()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java new file mode 100644 index 00000000..b044d4d2 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java @@ -0,0 +1,102 @@ +package at.asitplus.eidas.specific.connector.test.health; + +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/spring/SpringTest-context_healthcheck.xml" }) +@TestPropertySource(locations = {"classpath:/config/junit_config_1_springboot.properties"}) +@WebAppConfiguration +public class EidasNodeMetadataHealthIndicatorTest { + + @Autowired EidasNodeMetadataHealthIndicator health; + + private static MockWebServer mockWebServer = null; + + /** + * Testclass initializer. + * + * @throws IOException In case of an error + */ + @BeforeClass + public static void classInitializer() throws IOException { + mockWebServer = new MockWebServer(); + mockWebServer.start(40900); + mockWebServer.url("/mockup"); + + } + + @AfterClass + public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException, IOException { + mockWebServer.shutdown(); + + } + + @Test + public void httpStatusCode500() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(500) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus()); + + } + + @Test + public void httpStatusCode200() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.up().build().getStatus(), status.getStatus()); + + } + + @Test + public void noXmlResponse() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/config/log4j.properties"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java index a5876169..5f1c5dcf 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java @@ -51,7 +51,7 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xIniti import net.shibboleth.utilities.java.support.component.ComponentInitializationException; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({ "/applicationContext.xml", "/SpringTest_connector.beans.xml", "/eaaf_core.beans.xml", +@ContextConfiguration({ "/applicationContext.xml", "/spring/SpringTest_connector.beans.xml", "/eaaf_core.beans.xml", "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" }) @ActiveProfiles(profiles = {"deprecatedConfig"}) @WebAppConfiguration diff --git a/connector/src/test/resources/config/junit_config_1_springboot.properties b/connector/src/test/resources/config/junit_config_1_springboot.properties index ecb22dec..e63cda7b 100644 --- a/connector/src/test/resources/config/junit_config_1_springboot.properties +++ b/connector/src/test/resources/config/junit_config_1_springboot.properties @@ -13,7 +13,7 @@ eidas.ms.core.configRootDir=file:./src/test/resources/config/ eidas.ms.context.use.clustermode=true ##Monitoring -eidas.ms.monitoring.eIDASNode.metadata.url= +eidas.ms.monitoring.eIDASNode.metadata.url=http://localhost:40900/mockup ## extended validation of pending-request Id's eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret diff --git a/connector/src/test/resources/config/junit_config_2_springboot.properties b/connector/src/test/resources/config/junit_config_2_springboot.properties new file mode 100644 index 00000000..ecb22dec --- /dev/null +++ b/connector/src/test/resources/config/junit_config_2_springboot.properties @@ -0,0 +1,83 @@ +## embbeded Tomcat +tomcat.workingdir=./target/work +tomcat.ajp.enabled=true +tomcat.ajp.port=8009 +tomcat.ajp.networkAddress=127.0.0.1 +tomcat.ajp.additionalAttributes.secretrequired=true +tomcat.ajp.additionalAttributes.secret=junit + +## Basic service configuration +eidas.ms.context.url.prefix=http://localhost +eidas.ms.core.configRootDir=file:./src/test/resources/config/ + +eidas.ms.context.use.clustermode=true + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + +## eIDAS Ref. Implementation connector ### +eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://eidas.node/junit + +eidas.ms.auth.eIDAS.szrclient.useTestService=true +eidas.ms.auth.eIDAS.szrclient.endpoint.prod= +eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= + +#tech. AuthBlock signing for E-ID process +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair +eidas.ms.auth.eIDAS.authblock.keystore.path=keys/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + + +#Raw eIDAS Id data storage +eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false + + + +## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.type=jks +eidas.ms.pvp2.keystore.path=keys/junit.jks +eidas.ms.pvp2.keystore.password=password +eidas.ms.pvp2.key.metadata.alias=meta +eidas.ms.pvp2.key.metadata.password=password +eidas.ms.pvp2.key.signing.alias=sig +eidas.ms.pvp2.key.signing.password=password +eidas.ms.pvp2.metadata.validity=24 + +eidas.ms.pvp2.metadata.organisation.name=JUnit +eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit +eidas.ms.pvp2.metadata.organisation.url=http://junit.test +eidas.ms.pvp2.metadata.contact.givenname=Max +eidas.ms.pvp2.metadata.contact.surname=Mustermann +eidas.ms.pvp2.metadata.contact.email=max@junit.test + +## Service Provider configuration +eidas.ms.sp.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata +eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.0.pvp2.metadata.truststore.password=password +eidas.ms.sp.0.friendlyName=jUnit test +eidas.ms.sp.0.newEidMode=true + +#eidas.ms.sp.0.pvp2.metadata.url= +#eidas.ms.sp.0.policy.allowed.requested.targets=.* +#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false + +## Service Provider configuration +eidas.ms.sp.1.uniqueID=https://demo.egiz.gv.at/junit_test +eidas.ms.sp.1.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.1.pvp2.metadata.truststore.password=password +eidas.ms.sp.1.friendlyName=jUnit test +eidas.ms.sp.1.pvp2.metadata.url=http://junit.test/metadata +eidas.ms.sp.1.policy.allowed.requested.targets=test +eidas.ms.sp.1.policy.hasBaseIdTransferRestriction=true + diff --git a/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml b/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml new file mode 100644 index 00000000..3bac88e3 --- /dev/null +++ b/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/connector/src/test/resources/spring/SpringTest_connector.beans.xml b/connector/src/test/resources/spring/SpringTest_connector.beans.xml new file mode 100644 index 00000000..ba385cb9 --- /dev/null +++ b/connector/src/test/resources/spring/SpringTest_connector.beans.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java index 1091981e..ba3c46fe 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/main/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/Constants.java @@ -51,11 +51,11 @@ public class Constants { public static final String CONIG_PROPS_EIDAS_NODE_FORWARD_METHOD = CONIG_PROPS_EIDAS_NODE + ".forward.method"; public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_DEFAULT_ONLYNATURAL = - CONIG_PROPS_EIDAS_NODE + ".attributes.requested.onlynatural."; + CONIG_PROPS_EIDAS_NODE + ".attributes.requested.onlynatural"; public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_CC_SPECIFIC_ONLYNATURAL = - CONIG_PROPS_EIDAS_NODE + ".attributes.requested.{0}.onlynatural."; + CONIG_PROPS_EIDAS_NODE + ".attributes.requested.{0}.onlynatural"; public static final String CONIG_PROPS_EIDAS_NODE_ATTRIBUTES_REQUESTED_REPRESENTATION = - CONIG_PROPS_EIDAS_NODE + ".attributes.requested.representation."; + CONIG_PROPS_EIDAS_NODE + ".attributes.requested.representation"; public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_ADD_ALWAYS_PROVIDERNAME = CONIG_PROPS_EIDAS_NODE + ".workarounds.addAlwaysProviderName"; public static final String CONIG_PROPS_EIDAS_NODE_WORKAROUND_USEREQUESTIDASTRANSACTIONIDENTIFIER = diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java index ce48ed09..d0ab50f4 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/java/at/asitplus/eidas/specific/modules/auth/eidas/v2/test/validation/EidasRequestPreProcessingFirstTest.java @@ -37,6 +37,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; @@ -54,6 +55,7 @@ import eu.eidas.auth.commons.light.impl.LightRequest.Builder; @ContextConfiguration(locations = { "/SpringTest-context_tasks_test.xml", "/SpringTest-context_basic_realConfig.xml"}) +@TestPropertySource(locations = {"classpath:/config/junit_config_de_attributes.properties"}) @DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class EidasRequestPreProcessingFirstTest { @@ -73,9 +75,9 @@ public class EidasRequestPreProcessingFirstTest { */ @BeforeClass public static void classInitializer() throws IOException { - final String current = new java.io.File(".").toURI().toString(); - System.setProperty("eidas.ms.configuration", - current + "src/test/resources/config/junit_config_de_attributes.properties"); +// final String current = new java.io.File(".").toURI().toString(); +// System.setProperty("eidas.ms.configuration", +// current + "src/test/resources/config/junit_config_de_attributes.properties"); } diff --git a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties index 9cec2cb7..6b235667 100644 --- a/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties +++ b/eidas_modules/authmodule-eIDAS-v2/src/test/resources/config/junit_config_de_attributes.properties @@ -1,6 +1,8 @@ ## Basic service configuration eidas.ms.context.url.prefix= eidas.ms.context.url.request.validation=false +eidas.ms.core.configRootDir=file:./src/test/resources/config/ + eidas.ms.context.use.clustermode=true diff --git a/pom.xml b/pom.xml index a4ef7028..c8b9ae71 100644 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ 4.13.1 2.22.2 1.0.5 + 4.0.0 0.8.6 @@ -353,7 +354,12 @@ test test-jar - + + com.squareup.okhttp3 + mockwebserver + ${com.squareup.okhttp3.version} + test + -- cgit v1.2.3