/******************************************************************************* * 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.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; 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.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 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; } @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()))); return; } @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 (Exception e) { resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); resp.getWriter().write(MESSAGE_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 (Exception e) { result += e.getMessage() + "
"; } try { result += testStorage() + "
"; } catch (Exception e) { result += e.getMessage() + "
"; } try { result += testPVPMetadata() + "
"; } catch (Exception e) { result += e.getMessage() + "
"; } try { result += testEidasNodeMetadata() + "
"; } catch (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 { String key = Random.nextHexRandom16(); String value = Random.nextHexRandom16(); storage.put(key, value, -1); 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 (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 (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 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 { 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 //TODO: update if we switch to openSAML3 HttpClient httpClient = new HttpClient(); //set parameters HttpClientParams params = new HttpClientParams(); params.setSoTimeout(5*1000); httpClient.setParams(params ); //request URL HttpMethod method = new GetMethod(urlString); int respCode = httpClient.executeMethod(method); if (respCode != 200) { log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + " HTTP responsecode: " + respCode); throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR); } //parse metadata DOMUtils.parseXmlNonValidating(method.getResponseBodyAsStream()); 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); } } }