From 6fa8a9968e44fb5d56fc8d9c3ddd536a8997f7a9 Mon Sep 17 00:00:00 2001
From: Thomas <>
Date: Wed, 9 Mar 2022 13:49:51 +0100
Subject: refactor(core): split 'ms-connector' WebApp into 'core' and
'ms-connector' to reuse some code for 'ms-proxy' WebApp
# Conflicts:
# connector/src/main/resources/specific_eIDAS_connector.beans.xml
# connector/src/test/resources/spring/SpringTest_connector.beans.xml
# core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
# core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
# eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/IdAustriaAuthConstants.java
# eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/ReceiveFromIdAustriaSystemTask.java
# eidas_modules/authmodule_id-austria/src/main/java/at/asitplus/eidas/specific/modules/auth/idaustria/tasks/RequestIdAustriaSystemTask.java
# eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/controller/IdAustriaAuthMetadataControllerFirstTest.java
# eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/ReceiveAuthnResponseTaskTest.java
# eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/task/RequestIdAustriaSystemTaskTest.java
# eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthCredentialProviderTest.java
# eidas_modules/authmodule_id-austria/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/utils/IdAustriaAuthMetadataProviderFirstTest.java
# eidas_modules/authmodule_id-austria/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
# eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/MsProxyServiceConstants.java
# eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/EidasProxyServiceController.java
# eidas_modules/eidas_proxy-sevice/src/main/java/at/asitplus/eidas/specific/modules/msproxyservice/protocol/ProxyServiceAuthenticationAction.java
# eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/EidasProxyServiceControllerTest.java
# eidas_modules/eidas_proxy-sevice/src/test/java/at/asitplus/eidas/specific/modules/auth/idaustria/test/protocol/ProxyServiceAuthenticationActionTest.java
# eidas_modules/eidas_proxy-sevice/src/test/resources/spring/SpringTest-context_basic_mapConfig.xml
---
core_common_webapp/checks/spotbugs-exclude.xml | 12 +
core_common_webapp/pom.xml | 137 ++++++++
.../specific/core/SpringContextCloseHandler.java | 170 ++++++++++
.../specific/core/auth/AuthenticationManager.java | 60 ++++
.../core/builder/AuthenticationDataBuilder.java | 123 +++++++
.../core/config/StaticResourceConfiguration.java | 220 ++++++++++++
.../health/EidasNodeMetadataHealthIndicator.java | 69 ++++
.../core/health/IgniteClusterHealthIndicator.java | 52 +++
.../WebFrontEndSecurityInterceptor.java | 90 +++++
.../eidas/specific/core/logger/RevisionLogger.java | 110 ++++++
.../specific/core/logger/StatisticLogger.java | 141 ++++++++
.../eidas/specific/core/mapper/LoALevelMapper.java | 60 ++++
.../core/provider/StatusMessageProvider.java | 139 ++++++++
.../core/storage/CacheWithEidasBackend.java | 35 ++
.../EidasCacheTransactionStoreDecorator.java | 180 ++++++++++
.../storage/SimpleInMemoryTransactionStorage.java | 169 ++++++++++
.../core/storage/TransactionStoreElement.java | 70 ++++
.../main/resources/specific_eIDAS_core.beans.xml | 61 ++++
.../specific_eIDAS_core_storage.beans.xml | 39 +++
...sNodeMetadataHealthIndicatorNoEndpointTest.java | 70 ++++
.../EidasNodeMetadataHealthIndicatorTest.java | 102 ++++++
.../test/utils/AuthenticationDataBuilderTest.java | 369 +++++++++++++++++++++
.../config/junit_config_1_springboot.properties | 113 +++++++
.../config/junit_config_2_springboot.properties | 113 +++++++
.../resources/config/junit_config_3.properties | 148 +++++++++
.../src/test/resources/config/log4j.properties | 54 +++
.../src/test/resources/data/metadata_valid.xml | 106 ++++++
.../src/test/resources/data/test_idl_1.xml | 46 +++
.../spring/SpringTest-context_basic_test.xml | 22 ++
.../spring/SpringTest-context_healthcheck.xml | 22 ++
.../spring/SpringTest-context_simple_storage.xml | 15 +
.../resources/spring/SpringTest_core.beans.xml | 70 ++++
.../spring/SpringTest_core_config.beans.xml | 25 ++
33 files changed, 3212 insertions(+)
create mode 100644 core_common_webapp/checks/spotbugs-exclude.xml
create mode 100644 core_common_webapp/pom.xml
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java
create mode 100644 core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java
create mode 100644 core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml
create mode 100644 core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml
create mode 100644 core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java
create mode 100644 core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java
create mode 100644 core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
create mode 100644 core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties
create mode 100644 core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties
create mode 100644 core_common_webapp/src/test/resources/config/junit_config_3.properties
create mode 100644 core_common_webapp/src/test/resources/config/log4j.properties
create mode 100644 core_common_webapp/src/test/resources/data/metadata_valid.xml
create mode 100644 core_common_webapp/src/test/resources/data/test_idl_1.xml
create mode 100644 core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml
create mode 100644 core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml
create mode 100644 core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml
create mode 100644 core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml
create mode 100644 core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml
(limited to 'core_common_webapp')
diff --git a/core_common_webapp/checks/spotbugs-exclude.xml b/core_common_webapp/checks/spotbugs-exclude.xml
new file mode 100644
index 00000000..fbab3b53
--- /dev/null
+++ b/core_common_webapp/checks/spotbugs-exclude.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core_common_webapp/pom.xml b/core_common_webapp/pom.xml
new file mode 100644
index 00000000..2f58cefb
--- /dev/null
+++ b/core_common_webapp/pom.xml
@@ -0,0 +1,137 @@
+
+ 4.0.0
+
+ at.asitplus.eidas
+ ms_specific
+ 1.2.4-SNAPSHOT
+
+ at.asitplus.eidas.ms_specific
+ core_common_webapp
+ WebApplication commons
+
+
+
+ eIDASNode-local
+ local
+ file:${basedir}/../repository
+
+
+
+
+
+ at.asitplus.eidas.ms_specific
+ core_common_lib
+
+
+
+ at.gv.egiz.eaaf
+ eaaf-core
+
+
+
+
+ eu.eidas
+ eidas-jcache-ignite-specific-communication
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.thymeleaf
+ thymeleaf-spring5
+
+
+
+ javax.servlet
+ javax.servlet-api
+ provided
+
+
+
+
+
+ junit
+ junit
+ test
+
+
+ org.springframework
+ spring-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ at.gv.egiz.eaaf
+ eaaf_core_utils
+ test
+ test-jar
+
+
+ at.gv.egiz.eaaf
+ eaaf-core
+ test
+ test-jar
+
+
+ at.gv.egiz.eaaf
+ eaaf_module_pvp2_sp
+ test
+ test-jar
+
+
+ at.gv.egiz.eaaf
+ eaaf_module_pvp2_idp
+ test
+
+
+ at.gv.egiz.eaaf
+ eaaf_module_pvp2_idp
+ test
+ test-jar
+
+
+ com.squareup.okhttp3
+ mockwebserver
+ test
+
+
+
+
+
+
+ core_common_webapp
+
+
+
+
+ maven-surefire-plugin
+
+ 1
+
+
+
+ org.apache.maven.surefire
+ surefire-junit47
+ ${surefire.version}
+
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ ${spotbugs-maven-plugin.version}
+
+ checks/spotbugs-exclude.xml
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java
new file mode 100644
index 00000000..81f23841
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/SpringContextCloseHandler.java
@@ -0,0 +1,170 @@
+package at.asitplus.eidas.specific.core;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.slf4j.Logger;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextClosedEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+
+import at.gv.egiz.components.spring.api.IDestroyableObject;
+import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication;
+
+/**
+ * SpringContext CloseHandler.
+ *
+ * @author tlenz
+ *
+ */
+
+public class SpringContextCloseHandler
+ implements ApplicationListener, ApplicationContextAware, BeanPostProcessor {
+
+ private static final Logger log =
+ org.slf4j.LoggerFactory.getLogger(SpringContextCloseHandler.class);
+
+ private ApplicationContext context;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.
+ * springframework.context. ApplicationEvent)
+ */
+ @Override
+ @EventListener
+ public void onApplicationEvent(final ContextClosedEvent arg0) {
+ log.info("MS-specific eIDAS-Node shutdown process started ...");
+
+ try {
+ log.debug("CleanUp objects with implements the IDestroyable interface ... ");
+ final Map objectsToDestroy =
+ context.getBeansOfType(IDestroyableObject.class);
+ internalIDestroyableObject(objectsToDestroy);
+ log.info("Object cleanUp complete");
+
+ log.debug("Stopping Spring Thread-Pools ... ");
+ // shut-down task schedulers
+ final Map schedulers =
+ context.getBeansOfType(ThreadPoolTaskScheduler.class);
+ internalThreadPoolTaskScheduler(schedulers);
+
+ // shut-down task executors
+ final Map executers =
+ context.getBeansOfType(ThreadPoolTaskExecutor.class);
+ internalThreadPoolTaskExecutor(executers);
+ log.debug("Spring Thread-Pools stopped");
+
+
+ //clean-up eIDAS node
+ Map nodeIgnite =
+ context.getBeansOfType(IgniteInstanceInitializerSpecificCommunication.class);
+ log.info("Find #{} Apache Ignite instances from eIDAS Ref. impl.", nodeIgnite.size());
+ for (Entry el : nodeIgnite.entrySet()) {
+ if (el.getValue().getInstance() != null) {
+ el.getValue().getInstance().close();
+ el.getValue().destroyInstance();
+ log.debug("Shutdown Apache-Ignite: {}", el.getKey());
+
+ }
+ }
+
+ log.info("MS-specific eIDAS-Node shutdown process finished");
+
+ } catch (final Exception e) {
+ log.warn("MS-specific eIDAS-Node shutdown process has an error.", e);
+
+ }
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#
+ * postProcessAfterInitialization(java. lang.Object, java.lang.String)
+ */
+ @Override
+ public Object postProcessAfterInitialization(final Object arg0, final String arg1)
+ throws BeansException {
+ if (arg0 instanceof ThreadPoolTaskScheduler) {
+ ((ThreadPoolTaskScheduler) arg0).setWaitForTasksToCompleteOnShutdown(true);
+ }
+ if (arg0 instanceof ThreadPoolTaskExecutor) {
+ ((ThreadPoolTaskExecutor) arg0).setWaitForTasksToCompleteOnShutdown(true);
+ }
+ return arg0;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.beans.factory.config.BeanPostProcessor#
+ * postProcessBeforeInitialization(java .lang.Object, java.lang.String)
+ */
+ @Override
+ public Object postProcessBeforeInitialization(final Object arg0, final String arg1)
+ throws BeansException {
+ return arg0;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.context.ApplicationContextAware#setApplicationContext(org
+ * .springframework. context.ApplicationContext)
+ */
+ @Override
+ public void setApplicationContext(final ApplicationContext arg0) throws BeansException {
+ this.context = arg0;
+
+ }
+
+ private void internalThreadPoolTaskExecutor(final Map executers) {
+ for (final ThreadPoolTaskExecutor executor : executers.values()) {
+ executor.shutdown();
+ log.debug("Executer {} with active {} work has killed", executor.getThreadNamePrefix(),
+ executor.getActiveCount());
+
+ }
+
+ }
+
+ // Not required at the moment
+ private void internalThreadPoolTaskScheduler(
+ final Map schedulers) {
+ log.trace("Stopping #{} task-schedulers", schedulers.size());
+
+ }
+
+ private void internalIDestroyableObject(final Map objectsToDestroy) {
+ if (objectsToDestroy != null) {
+ final Iterator> interator =
+ objectsToDestroy.entrySet().iterator();
+ while (interator.hasNext()) {
+ final Entry object = interator.next();
+ try {
+ object.getValue().fullyDestroy();
+ log.debug("Object with ID: {} is destroyed", object.getKey());
+
+ } catch (final Exception e) {
+ log.warn("Destroing object with ID: {} FAILED!", object.getKey(), null, e);
+
+ }
+ }
+ }
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java
new file mode 100644
index 00000000..6be1f0ba
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/auth/AuthenticationManager.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.auth;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext;
+import at.gv.egiz.eaaf.core.api.idp.slo.ISloInformationContainer;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.idp.auth.AbstractAuthenticationManager;
+import at.gv.egiz.eaaf.core.impl.idp.controller.protocols.RequestImpl;
+
+@Service("AuthenticationManager")
+public class AuthenticationManager extends AbstractAuthenticationManager {
+ private static final Logger log = LoggerFactory.getLogger(AuthenticationManager.class);
+
+ @Override
+ public ISloInformationContainer performSingleLogOut(HttpServletRequest httpReq,
+ HttpServletResponse httpResp,
+ IRequest pendingReq, String internalSsoId) throws EaafException {
+ throw new RuntimeException("Single LogOut is NOT supported by this implementation");
+
+ }
+
+ @Override
+ protected void populateExecutionContext(ExecutionContext executionContext,
+ RequestImpl pendingReq, HttpServletRequest httpReq)
+ throws EaafException {
+ log.trace("No implementation-specific population of execution-context required ... ");
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
new file mode 100644
index 00000000..9580a62f
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/builder/AuthenticationDataBuilder.java
@@ -0,0 +1,123 @@
+/*
+ * 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.core.builder;
+
+import java.util.Date;
+
+import org.springframework.stereotype.Service;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IAuthProcessDataContainer;
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+import at.gv.egiz.eaaf.core.impl.data.Pair;
+import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.auth.builder.AbstractAuthenticationDataBuilder;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import lombok.extern.slf4j.Slf4j;
+
+@Service("AuthenticationDataBuilder")
+@Slf4j
+public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder {
+
+ @Override
+ protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException {
+ final EidAuthProcessDataWrapper authProcessData =
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class);
+ EidAuthenticationData authData = new EidAuthenticationData();
+
+ //set basis infos
+ super.generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData);
+
+ // set specific informations
+ authData.setSsoSessionValidTo(
+ new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000));
+
+ authData.setEidStatus(authProcessData.isTestIdentity()
+ ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY);
+
+ return authData;
+
+ }
+
+ @Override
+ protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq)
+ throws EaafException {
+ if (authData instanceof EidAuthenticationData) {
+ ((EidAuthenticationData)authData).setGenericData(
+ ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME,
+ pendingReq.getUniquePiiTransactionIdentifier());
+ log.trace("Inject piiTransactionId: {} into AuthData", pendingReq.getUniquePiiTransactionIdentifier());
+
+ // set specific informations
+ ((EidAuthenticationData)authData).setSsoSessionValidTo(
+ new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000));
+
+ //set E-ID status-level
+ final EidAuthProcessDataWrapper authProcessData =
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class);
+ ((EidAuthenticationData)authData).setEidStatus(authProcessData.isTestIdentity()
+ ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY);
+
+ } else {
+ throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: "
+ + authData.getClass().getName());
+
+ }
+
+ }
+
+ @Override
+ protected IAuthData getAuthDataInstance(IRequest arg0) throws EaafException {
+ return new EidAuthenticationData();
+
+ }
+
+ @Override
+ protected Pair buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData)
+ throws EaafBuilderException {
+ return super.buildOAspecificbPK(pendingReq, authData);
+
+ }
+
+ @Override
+ protected Pair getEncryptedBpkFromPvpAttribute(IAuthProcessDataContainer arg0,
+ AuthenticationData arg1, ISpConfiguration arg2) throws EaafBuilderException {
+ return null;
+
+ }
+
+ @Override
+ protected Pair getbaseIdFromSzr(AuthenticationData arg0, String arg1, String arg2) {
+ return null;
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java
new file mode 100644
index 00000000..06377c3f
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/config/StaticResourceConfiguration.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2019 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.core.config;
+
+import java.net.MalformedURLException;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ReloadableResourceBundleMessageSource;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.CookieLocaleResolver;
+import org.thymeleaf.templateresolver.FileTemplateResolver;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.logging.IMessageSourceLocation;
+import at.gv.egiz.eaaf.core.impl.utils.FileUtils;
+
+/**
+ * Spring configurator for Web resources.
+ *
+ * @author tlenz
+ *
+ */
+@Configuration
+public class StaticResourceConfiguration implements WebMvcConfigurer {
+ private static final Logger log = LoggerFactory.getLogger(StaticResourceConfiguration.class);
+ private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
+ "/"
+ };
+
+ private static final String DEFAULT_MESSAGE_SOURCE = "classpath:properties/status_messages";
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ final String staticResources = basicConfig.getBasicConfiguration(
+ MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_STATIC_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ String absPath = FileUtils.makeAbsoluteUrl(staticResources, basicConfig
+ .getConfigurationRootDirectory());
+ if (!absPath.endsWith("/")) {
+ absPath += "/";
+ }
+
+ registry.addResourceHandler("/static/**").addResourceLocations(absPath);
+ log.info("Add Ressourcefolder: " + absPath + " for static Web content");
+
+ } else {
+ log.debug("No Ressourcefolder for static Web content");
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for static Web content", e);
+
+ }
+
+ registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
+
+ }
+
+ /**
+ * Get a message source with only internal message properties.
+ *
+ * @param ressourceLocations List of source-locations
+ * @return
+ */
+ @Bean
+ public ReloadableResourceBundleMessageSource internalMessageSource(
+ @Autowired(required = false) final List ressourceLocations) {
+ final ReloadableResourceBundleMessageSource messageSource =
+ new ReloadableResourceBundleMessageSource();
+
+ // add default message source
+ messageSource.setBasename(DEFAULT_MESSAGE_SOURCE);
+
+ if (ressourceLocations != null) {
+ // load more message sources
+ for (final IMessageSourceLocation el : ressourceLocations) {
+ if (el.getMessageSourceLocation() != null) {
+ for (final String source : el.getMessageSourceLocation()) {
+ messageSource.addBasenames(source);
+ log.debug("Add additional messageSources: {}", el.getMessageSourceLocation().toArray());
+
+ }
+ }
+ }
+ }
+
+ messageSource.setDefaultEncoding("UTF-8");
+ return messageSource;
+
+ }
+
+ /**
+ * Get full message source with internal and external message-properties files.
+ *
+ * @param ressourceLocations List of source-locations
+ * @return
+ */
+ @Bean
+ public ReloadableResourceBundleMessageSource messageSource(
+ @Autowired(required = false) final List ressourceLocations) {
+ final ReloadableResourceBundleMessageSource messageSource =
+ new ReloadableResourceBundleMessageSource();
+ messageSource.setDefaultEncoding("UTF-8");
+ messageSource.setParentMessageSource(internalMessageSource(ressourceLocations));
+
+ final String staticResources = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ final String absPath =
+ FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory());
+ messageSource.setBasename(absPath);
+
+ } else {
+ log.debug("No Ressourcefolder for dynamic Web content templates");
+
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e);
+
+ }
+
+ return messageSource;
+
+ }
+
+ /**
+ * Get a i18n resolver based on cookies.
+ *
+ * @return
+ */
+ @Bean
+ public CookieLocaleResolver localeResolver() {
+ final CookieLocaleResolver localeResolver = new CookieLocaleResolver();
+ localeResolver.setCookieName("currentLanguage");
+ localeResolver.setCookieMaxAge(3600);
+ return localeResolver;
+
+ }
+
+ /**
+ * Get a Tyhmeleaf Template-Resolver with external configuration path.
+ *
+ * @return
+ */
+ @Bean(name = "templateResolver")
+ public FileTemplateResolver templateResolver() {
+ final String staticResources = basicConfig
+ .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_PATH);
+ try {
+ if (StringUtils.isNotEmpty(staticResources)) {
+ String absPath =
+ FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory());
+ if (!absPath.endsWith("/")) {
+ absPath += "/";
+
+ }
+
+ if (absPath.startsWith("file:")) {
+ absPath = absPath.substring("file:".length());
+
+ }
+
+ final FileTemplateResolver viewResolver = new FileTemplateResolver();
+ viewResolver.setPrefix(absPath);
+ viewResolver.setSuffix(".html");
+ viewResolver.setTemplateMode("HTML");
+ viewResolver.setCacheable(false);
+
+ log.info("Add Ressourcefolder: {} for dynamic Web content templates", absPath);
+ return viewResolver;
+
+ } else {
+ log.debug("No Ressourcefolder for dynamic Web content templates");
+
+ }
+
+ } catch (final MalformedURLException e) {
+ log.warn("Can NOT initialize ressourcefolder for dynamic Web content templates", e);
+
+ }
+
+ throw new RuntimeException("Can NOT initialize HTML template resolver");
+
+ }
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java
new file mode 100644
index 00000000..754fe9ab
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/EidasNodeMetadataHealthIndicator.java
@@ -0,0 +1,69 @@
+package at.asitplus.eidas.specific.core.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.core.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/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java
new file mode 100644
index 00000000..651f9125
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/health/IgniteClusterHealthIndicator.java
@@ -0,0 +1,52 @@
+package at.asitplus.eidas.specific.core.health;
+
+import org.apache.ignite.Ignite;
+import org.springframework.boot.actuate.health.Health;
+import org.springframework.boot.actuate.health.HealthIndicator;
+
+import eu.eidas.auth.cache.IgniteInstanceInitializerSpecificCommunication;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * HealthCheck that validate Nodes in Apache-Ignite Cluster.
+ *
+ * @author tlenz
+ *
+ */
+@Slf4j
+public class IgniteClusterHealthIndicator implements HealthIndicator {
+
+ @Setter
+ protected IgniteInstanceInitializerSpecificCommunication igniteInstanceInitializerSpecificCommunication;
+
+ @Override
+ public Health health() {
+ final Ignite instance = igniteInstanceInitializerSpecificCommunication.getInstance();
+
+ // check if Apache Ignite cluster is active
+ if (!instance.cluster().active()) {
+ return Health.outOfService().build();
+
+ }
+
+ final Health.Builder healthBuilder;
+ // Status UP requires more than 1 node because MS-Connector and eIDAS-Node operations as
+ // micro-services
+ if (instance.cluster().nodes().size() > 1) {
+ healthBuilder = Health.up();
+
+ } else {
+ // Something looks wrong if only a single node was found because MS-Connector and eIDAS-Node
+ // operations as micro-services
+ healthBuilder = Health.outOfService();
+
+ }
+
+ healthBuilder.withDetail("#Nodes", instance.cluster().nodes().size());
+ log.trace("Ignite state. #Nodes: {}", instance.cluster().nodes().size());
+ return healthBuilder.build();
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java
new file mode 100644
index 00000000..f665be51
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/interceptor/WebFrontEndSecurityInterceptor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.core.interceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Spring interceptor to inject securtiy headers into http response.
+ *
+ * @author tlenz
+ *
+ */
+public class WebFrontEndSecurityInterceptor implements HandlerInterceptor {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.
+ * http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object)
+ */
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
+ throws Exception {
+
+ // set security headers
+ response.setHeader("Expires", "Sat, 6 May 1995 12:00:00 GMT");
+ response.setHeader("Pragma", "no-cache");
+ response.setHeader("Cache-control", "no-store, no-cache, must-revalidate");
+
+ return true;
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.
+ * http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object, org.springframework.web.servlet.ModelAndView)
+ */
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+ ModelAndView modelAndView) throws Exception {
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.
+ * servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse,
+ * java.lang.Object, java.lang.Exception)
+ */
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
+ Exception ex)
+ throws Exception {
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java
new file mode 100644
index 00000000..03a56976
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/RevisionLogger.java
@@ -0,0 +1,110 @@
+/*
+ * 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.core.logger;
+
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.components.eventlog.api.Event;
+import at.gv.egiz.components.eventlog.api.EventConstants;
+import at.gv.egiz.components.eventlog.api.EventLogFactory;
+import at.gv.egiz.components.eventlog.api.EventLoggingException;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration;
+import at.gv.egiz.eaaf.core.api.logging.IRevisionLogger;
+
+public class RevisionLogger extends EventLogFactory implements IRevisionLogger {
+ private static final Logger log = LoggerFactory.getLogger(RevisionLogger.class);
+
+ @Autowired
+ private IConfiguration basicConfig;
+
+ @Override
+ public void logEvent(ISpConfiguration oaConfig, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message));
+
+ }
+
+ @Override
+ public void logEvent(IRequest pendingRequest, int eventCode) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode,
+ pendingRequest.getUniqueSessionIdentifier(), pendingRequest.getUniqueTransactionIdentifier()));
+
+ }
+
+ @Override
+ public void logEvent(IRequest pendingRequest, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message,
+ pendingRequest.getUniqueSessionIdentifier(), pendingRequest.getUniqueTransactionIdentifier()));
+
+ }
+
+ @Override
+ public void logEvent(int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message));
+
+ }
+
+ @Override
+ public void logEvent(String sessionID, String transactionID, int eventCode, String message) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, message, sessionID, transactionID));
+
+ }
+
+ @Override
+ public void logEvent(String sessionID, String transactionID, int eventCode) {
+ logEvent(createNewEvent(new Date().getTime(), eventCode, sessionID, transactionID));
+
+ }
+
+ private void logEvent(Event event) {
+ try {
+ if (event.getEventCode() >= 1100) {
+ if (event.getEventCode() == EventConstants.TRANSACTION_IP
+ && !basicConfig.getBasicConfigurationBoolean(
+ MsEidasNodeConstants.PROP_CONFIG_REVISIONLOG_LOG_IP_ADDRESS_OF_USER, true)) {
+ log.trace("Ignore Event: " + event.getEventCode() + " because IP adresse logging prohibited");
+ return;
+
+ }
+
+ getEventLog().logEvent(event);
+
+ } else {
+ log.trace("Ignore Event: " + event.getEventCode()
+ + " because session functionallity is not implemented");
+ }
+
+ } catch (final EventLoggingException e) {
+ log.warn("Event logging FAILED! Reason: " + e.getMessage());
+
+ }
+
+ }
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java
new file mode 100644
index 00000000..bdaf83f6
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/logger/StatisticLogger.java
@@ -0,0 +1,141 @@
+/*
+ * 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.core.logger;
+
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.gv.egiz.eaaf.core.api.IRequest;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.logging.IStatisticLogger;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+public class StatisticLogger implements IStatisticLogger {
+
+ private static final Logger log = LoggerFactory.getLogger(StatisticLogger.class);
+
+ private static final String DATEFORMATER = "yyyy.MM.dd-HH:mm:ss+z";
+ private static final String STATUS_SUCCESS = "success";
+ private static final String STATUS_ERROR = "error";
+
+ @Override
+ public void logSuccessOperation(IRequest protocolRequest, IAuthData authData, boolean isSsoSession) {
+ log.info(buildLogMessage(
+ protocolRequest.getUniqueTransactionIdentifier(),
+ protocolRequest.getSpEntityId(),
+ protocolRequest.getRawData(MsEidasNodeConstants.DATA_REQUESTERID),
+ protocolRequest.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ authData.getCiticenCountryCode(),
+ STATUS_SUCCESS,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY));
+
+ }
+
+ @Override
+ public void logErrorOperation(Throwable throwable) {
+ String errorId = "TODO";
+ if (throwable instanceof EaafException) {
+ errorId = ((EaafException) throwable).getErrorId();
+ }
+
+ log.info(buildLogMessage(
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+
+ }
+
+ @Override
+ public void logErrorOperation(Throwable throwable, IRequest errorRequest) {
+ String errorId = "TODO";
+ if (throwable instanceof EaafException) {
+ errorId = ((EaafException) throwable).getErrorId();
+ }
+
+ if (errorRequest != null) {
+ log.info(buildLogMessage(
+ errorRequest.getUniqueTransactionIdentifier(),
+ errorRequest.getSpEntityId(),
+ errorRequest.getRawData(MsEidasNodeConstants.DATA_REQUESTERID),
+ errorRequest.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier(),
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+ } else {
+ log.info(buildLogMessage(
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ StringUtils.EMPTY,
+ STATUS_ERROR,
+ errorId,
+ throwable.getMessage()));
+ }
+
+ }
+
+ @Override
+ public void internalTesting() throws Exception {
+ log.trace("Not implemented for a File-based logger");
+
+ }
+
+ private String buildLogMessage(String transId, String entityId, Object requesterId, String target,
+ String cc,
+ String status, String errorCode, String errorMsg) {
+ String logMsg = StringUtils.EMPTY;
+
+ // data,tId,MOAID-Id,SP-Id,bPKTarget,CC,status,error-code,error-msg
+
+ logMsg += DateTime.now().toString(DATEFORMATER) + ",";
+ logMsg += transId + ",";
+ logMsg += entityId + ",";
+
+ if (requesterId instanceof String && StringUtils.isNotEmpty((String) requesterId)) {
+ logMsg += (String) requesterId + ",";
+ } else {
+ logMsg += StringUtils.EMPTY + ",";
+ }
+
+ logMsg += target + ",";
+ logMsg += cc + ",";
+
+ logMsg += status + ",";
+ logMsg += errorCode + ",";
+ logMsg += errorMsg;
+
+ return logMsg;
+ }
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java
new file mode 100644
index 00000000..e3ab5d45
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/mapper/LoALevelMapper.java
@@ -0,0 +1,60 @@
+/*
+ * 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.core.mapper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ILoALevelMapper;
+
+@Service("LoALevelMapper")
+public class LoALevelMapper implements ILoALevelMapper {
+ private static final Logger log = LoggerFactory.getLogger(LoALevelMapper.class);
+
+ @Override
+ public String mapToSecClass(String loa) {
+ log.info("Mapping to PVP SecClass is NOT supported");
+ return null;
+ }
+
+ @Override
+ public String mapToEidasLoa(String loa) {
+ if (loa.startsWith(EaafConstants.EIDAS_LOA_PREFIX)) {
+ return loa;
+ } else {
+ log.info("Can NOT map '" + loa + "' to eIDAS LoA");
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public String mapEidasQaaToStorkQaa(String eidasqaaLevel) {
+ return null;
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java
new file mode 100644
index 00000000..e86d50d3
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/provider/StatusMessageProvider.java
@@ -0,0 +1,139 @@
+/*
+ * 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.core.provider;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import at.gv.egiz.eaaf.core.api.IStatusMessenger;
+import at.gv.egiz.eaaf.core.exceptions.EaafException;
+
+@Service("StatusMessageProvider")
+public class StatusMessageProvider implements IStatusMessenger {
+ private static final Logger log = LoggerFactory.getLogger(StatusMessageProvider.class);
+
+ private static final String ERROR_MESSAGES_UNAVAILABLE =
+ "Error messages can NOT be load from application. Only errorCode: {0} is availabe";
+ private static final String ERROR_NO_MESSAGE = "No errormesseage for error with number.={0}";
+
+ private static final String ERROR_EXTERNALERROR_CODES_UNAVAILABLE =
+ "External error-codes can NOT be load from application. Only internal errorCode: {0} is availabe";
+ private static final String ERROR_NO_EXTERNALERROR_CODE =
+ "No external error for internal error with number.={0}";
+
+ // internal messanges
+ private static final String DEFAULT_MESSAGE_RESOURCES = "properties/status_messages_en";
+ private static final Locale DEFAULT_MESSAGE_LOCALES = new Locale("en", "GB");
+ private ResourceBundle messages;
+
+ // external error codes
+ private static final String DEFAULT_EXTERNALERROR_RESOURCES = "properties/external_statuscodes_map";
+ private static final Locale DEFAULT_EXTERNALERROR_LOCALES = new Locale("en", "GB");
+ private ResourceBundle externalError = null;
+
+ @Override
+ public String getMessageWithoutDefault(String messageId, Object[] parameters) {
+ // initialize messages
+ if (messages == null) {
+ this.messages = ResourceBundle.getBundle(
+ DEFAULT_MESSAGE_RESOURCES,
+ DEFAULT_MESSAGE_LOCALES);
+
+ }
+
+ // create the message
+ if (messages == null) {
+ return MessageFormat.format(ERROR_MESSAGES_UNAVAILABLE, new Object[] { messageId });
+
+ } else {
+ final String rawMessage = messages.getString(messageId);
+ return MessageFormat.format(rawMessage, parameters);
+
+ }
+ }
+
+ @Override
+ public String getMessage(String messageId, Object[] parameters) {
+ try {
+ return getMessageWithoutDefault(messageId, parameters);
+
+ } catch (final MissingResourceException e2) {
+ return MessageFormat.format(ERROR_NO_MESSAGE, new Object[] { messageId });
+
+ }
+ }
+
+ @Override
+ public String getResponseErrorCode(Throwable throwable) {
+ String errorCode = IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+ if (throwable instanceof EaafException) {
+ errorCode = ((EaafException) throwable).getErrorId();
+
+ }
+
+ return errorCode;
+
+ }
+
+ @Override
+ public String mapInternalErrorToExternalError(String intErrorCode) {
+ // initialize messages
+ if (externalError == null) {
+ this.externalError = ResourceBundle.getBundle(
+ DEFAULT_EXTERNALERROR_RESOURCES,
+ DEFAULT_EXTERNALERROR_LOCALES);
+
+ }
+
+ // create the message
+ if (externalError == null) {
+ log.warn(MessageFormat.format(ERROR_EXTERNALERROR_CODES_UNAVAILABLE, new Object[] { intErrorCode }));
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ } else {
+ try {
+ if (StringUtils.isNotEmpty(intErrorCode)) {
+ return externalError.getString(intErrorCode);
+
+ } else {
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ }
+
+ } catch (final MissingResourceException e2) {
+ log.info(MessageFormat.format(ERROR_NO_EXTERNALERROR_CODE, new Object[] { intErrorCode }));
+ return IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC;
+
+ }
+ }
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java
new file mode 100644
index 00000000..0eeb35d9
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/CacheWithEidasBackend.java
@@ -0,0 +1,35 @@
+/*
+ * 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.core.storage;
+
+import eu.eidas.auth.commons.cache.ConcurrentCacheService;
+import eu.eidas.auth.commons.tx.AbstractCache;
+
+public class CacheWithEidasBackend extends AbstractCache {
+
+ protected CacheWithEidasBackend(ConcurrentCacheService concurrentMapService) {
+ super(concurrentMapService);
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java
new file mode 100644
index 00000000..9b1c8eae
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/EidasCacheTransactionStoreDecorator.java
@@ -0,0 +1,180 @@
+/*
+ * 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.core.storage;
+
+import java.util.Arrays;
+import java.util.Date;
+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, 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)) {
+ final TransactionStoreElement el = storage.get(oldKey);
+ el.setKey(newKey);
+ el.setData(value);
+ storage.put(newKey, el);
+ boolean delResult = storage.remove(oldKey);
+ log.trace("Object: {} removed from cache: {}", oldKey, delResult);
+
+ } else {
+ throw new EaafStorageException("No element in TransactionStorage with key: " + oldKey);
+ }
+
+ }
+
+ @Override
+ public List clean(Date now, long dataTimeOut) {
+ log.info("Clean is NOT implemented, because its not needed");
+ return Arrays.asList();
+
+ }
+
+ @Override
+ public boolean containsKey(String key) {
+ return storage.containsKey(key);
+
+ }
+
+ @Override
+ public Object get(String key) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement element = storage.get(key);
+ return element.getData();
+
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public T get(String key, Class type) throws EaafException {
+ return get(key, type, -1);
+
+ }
+
+ @Override
+ public T get(String key, Class type, long dataTimeOut) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement value = storage.get(key);
+
+ if (dataTimeOut > -1) {
+ final long now = new Date().getTime();
+ if (now - value.getCreated().getTime() > dataTimeOut) {
+ log.info("Transaction-Data with key: " + key + " is out of time.");
+ throw new EaafStorageException("Transaction-Data with key: " + key + " is out of time.");
+
+ }
+ }
+
+ if (type.isAssignableFrom(value.getData().getClass())) {
+ return (T) value.getData();
+
+ } else {
+ log.warn("Can NOT cast '" + value.getClass() + "' to '" + type + "'");
+ }
+
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object getRaw(String key) throws EaafException {
+ return storage.get(key);
+
+ }
+
+ @Override
+ public void put(String key, Object value, int dataTimeOut) throws EaafException {
+ final TransactionStoreElement element = new TransactionStoreElement();
+ element.setKey(key);
+ element.setData(value);
+ storage.put(key, element);
+
+ }
+
+ @Override
+ public void putRaw(String key, Object value) throws EaafException {
+ if (value instanceof TransactionStoreElement) {
+ storage.put(((TransactionStoreElement) value).getKey(), (TransactionStoreElement) value);
+ } else {
+ log.info(value.getClass().getName() + " is NOT a RAW element of " + ITransactionStorage.class
+ .getName());
+ }
+
+ }
+
+ @Override
+ public void remove(String key) {
+ if (containsKey(key)) {
+ log.debug("Remove element with key: " + key + " from " + ITransactionStorage.class.getName());
+ boolean delResult = storage.remove(key);
+ log.trace("Object: {} removed from cache: {}", key, delResult);
+
+ }
+ }
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java
new file mode 100644
index 00000000..a3a8af0f
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/SimpleInMemoryTransactionStorage.java
@@ -0,0 +1,169 @@
+/*
+ * 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.core.storage;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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;
+
+public class SimpleInMemoryTransactionStorage implements ITransactionStorage {
+ private static final Logger log = LoggerFactory.getLogger(SimpleInMemoryTransactionStorage.class);
+
+ private final Map storage =
+ new ConcurrentHashMap<>();
+
+ @Override
+ public void changeKey(String oldKey, String newKey, Object value) throws EaafException {
+ if (containsKey(oldKey)) {
+ final TransactionStoreElement el = storage.get(oldKey);
+ el.setKey(newKey);
+ storage.put(newKey, el);
+ storage.remove(oldKey);
+
+ } else {
+ throw new EaafStorageException("No element in TransactionStorage with key: " + oldKey);
+ }
+
+ }
+
+ @Override
+ public List clean(Date now, long dataTimeOut) {
+ final List result = new ArrayList<>();
+ final Iterator> iterator = storage.entrySet().iterator();
+ while (iterator.hasNext()) {
+ final Entry key = iterator.next();
+ synchronized (storage) {
+ if (storage.containsKey(key.getKey())) {
+ final TransactionStoreElement element = key.getValue();
+ if (now.getTime() - element.getCreated().getTime() > dataTimeOut) {
+ result.add(key.getKey());
+ }
+ }
+ }
+ }
+
+ return result;
+
+ }
+
+ @Override
+ public boolean containsKey(String key) {
+ if (key != null) {
+ return storage.containsKey(key);
+ } else {
+ return false;
+ }
+
+ }
+
+ @Override
+ public Object get(String key) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement element = storage.get(key);
+ return element.getData();
+
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public T get(String key, Class type) throws EaafException {
+ return get(key, type, -1);
+
+ }
+
+ @Override
+ public T get(String key, Class type, long dataTimeOut) throws EaafException {
+ if (key != null && containsKey(key)) {
+ final TransactionStoreElement value = storage.get(key);
+
+ if (dataTimeOut > -1) {
+ final long now = new Date().getTime();
+ if (now - value.getCreated().getTime() > dataTimeOut) {
+ log.info("Transaction-Data with key: " + key + " is out of time.");
+ throw new EaafStorageException("Transaction-Data with key: " + key + " is out of time.");
+
+ }
+ }
+
+ if (type.isAssignableFrom(value.getData().getClass())) {
+ return (T) value.getData();
+
+ } else {
+ log.warn("Can NOT cast '" + value.getClass() + "' to '" + type + "'");
+ }
+
+ }
+
+ return null;
+ }
+
+ @Override
+ public Object getRaw(String key) throws EaafException {
+ return storage.get(key);
+
+ }
+
+ @Override
+ public void put(String key, Object value, int dataTimeOut) throws EaafException {
+ final TransactionStoreElement element = new TransactionStoreElement();
+ element.setKey(key);
+ element.setData(value);
+ storage.put(key, element);
+
+ }
+
+ @Override
+ public void putRaw(String key, Object value) throws EaafException {
+ if (value instanceof TransactionStoreElement) {
+ storage.put(((TransactionStoreElement) value).getKey(), (TransactionStoreElement) value);
+ } else {
+ log.info(value.getClass().getName() + " is NOT a RAW element of " + ITransactionStorage.class
+ .getName());
+ }
+
+ }
+
+ @Override
+ public void remove(String key) {
+ if (containsKey(key)) {
+ log.debug("Remove element with key: " + key + " from " + ITransactionStorage.class.getName());
+ storage.remove(key);
+
+ }
+ }
+
+}
diff --git a/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java
new file mode 100644
index 00000000..48668d4b
--- /dev/null
+++ b/core_common_webapp/src/main/java/at/asitplus/eidas/specific/core/storage/TransactionStoreElement.java
@@ -0,0 +1,70 @@
+/*
+ * 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.core.storage;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class TransactionStoreElement implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private String key = null;
+ private Object data = null;
+ private Date created;
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public Object getData() {
+ return data;
+ }
+
+ public void setData(Object data) {
+ this.data = data;
+ }
+
+ public Date getCreated() {
+ return copyOrNull(created);
+ }
+
+ public void setCreated(Date created) {
+ this.created = copyOrNull(created);
+ }
+
+ private Date copyOrNull(Date in) {
+ if (in != null) {
+ return new Date(in.getTime());
+
+ }
+
+ return null;
+
+ }
+
+}
diff --git a/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml b/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml
new file mode 100644
index 00000000..f37dc451
--- /dev/null
+++ b/core_common_webapp/src/main/resources/specific_eIDAS_core.beans.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml b/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml
new file mode 100644
index 00000000..259f5605
--- /dev/null
+++ b/core_common_webapp/src/main/resources/specific_eIDAS_core_storage.beans.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java
new file mode 100644
index 00000000..06ce8abe
--- /dev/null
+++ b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java
@@ -0,0 +1,70 @@
+package at.asitplus.eidas.specific.core.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.core.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/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java
new file mode 100644
index 00000000..e8bc7817
--- /dev/null
+++ b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/health/EidasNodeMetadataHealthIndicatorTest.java
@@ -0,0 +1,102 @@
+package at.asitplus.eidas.specific.core.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.core.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/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
new file mode 100644
index 00000000..12936a59
--- /dev/null
+++ b/core_common_webapp/src/test/java/at/asitplus/eidas/specific/core/test/utils/AuthenticationDataBuilderTest.java
@@ -0,0 +1,369 @@
+package at.asitplus.eidas.specific.core.test.utils;
+
+import static at.asitplus.eidas.specific.core.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE;
+
+import java.io.IOException;
+import java.security.PublicKey;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.RandomUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.opensaml.core.config.InitializationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import org.w3c.dom.Element;
+
+import at.asitplus.eidas.specific.core.MsEidasNodeConstants;
+import at.asitplus.eidas.specific.core.builder.AuthenticationDataBuilder;
+import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants;
+import at.gv.egiz.eaaf.core.api.data.EaafConstants;
+import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions;
+import at.gv.egiz.eaaf.core.api.data.PvpAttributeDefinitions.EidIdentityStatusLevelValues;
+import at.gv.egiz.eaaf.core.api.idp.IAuthData;
+import at.gv.egiz.eaaf.core.api.idp.IConfiguration;
+import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
+import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException;
+import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException;
+import at.gv.egiz.eaaf.core.exceptions.EaafParserException;
+import at.gv.egiz.eaaf.core.exceptions.EaafStorageException;
+import at.gv.egiz.eaaf.core.impl.builder.BpkBuilder;
+import at.gv.egiz.eaaf.core.impl.idp.EidAuthenticationData;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.EidAuthProcessDataWrapper;
+import at.gv.egiz.eaaf.core.impl.idp.auth.data.SimpleIdentityLinkAssertionParser;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.DummySpConfiguration;
+import at.gv.egiz.eaaf.core.impl.idp.module.test.TestRequestImpl;
+import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration({ "/spring/SpringTest_core_config.beans.xml", "/spring/SpringTest_core.beans.xml", "/eaaf_core.beans.xml",
+ "/eaaf_pvp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" })
+@ActiveProfiles(profiles = {"deprecatedConfig"})
+@WebAppConfiguration
+public class AuthenticationDataBuilderTest {
+
+ @Autowired
+ private AuthenticationDataBuilder authenticationDataBuilder;
+
+ @Autowired(required = true)
+ private IConfiguration basicConfig;
+
+ private MockHttpServletRequest httpReq;
+ private MockHttpServletResponse httpResp;
+ private TestRequestImpl pendingReq;
+
+ private DummySpConfiguration oaParam;
+
+ private String eidasBind;
+ private String authBlock;
+
+ @BeforeClass
+ public static void classInitializer() throws InitializationException, ComponentInitializationException {
+ final String current = new java.io.File(".").toURI().toString();
+ System.setProperty("eidas.ms.configuration", current
+ + "src/test/resources/config/junit_config_3.properties");
+
+ EaafOpenSaml3xInitializer.eaafInitialize();
+ }
+
+ @Before
+ public void initialize() throws EaafStorageException {
+ httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector");
+ httpResp = new MockHttpServletResponse();
+ RequestContextHolder.resetRequestAttributes();
+ RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp));
+
+ final Map spConfig = new HashMap<>();
+ spConfig.put(EaafConfigConstants.SERVICE_UNIQUEIDENTIFIER, "testSp");
+ spConfig.put("target", "urn:publicid:gv.at:cdid+XX");
+ spConfig.put(PROP_CONFIG_SP_NEW_EID_MODE, "true");
+ oaParam = new DummySpConfiguration(spConfig, basicConfig);
+
+ pendingReq = new TestRequestImpl();
+ pendingReq.setAuthUrl("https://localhost/ms_connector");
+ pendingReq.setPendingReqId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setPiiTransactionId(RandomStringUtils.randomAlphanumeric(10));
+ pendingReq.setSpConfig(oaParam);
+ authBlock = RandomStringUtils.randomAlphanumeric(20);
+ eidasBind = RandomStringUtils.randomAlphanumeric(20);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, authBlock);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setGenericDataToSession(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, eidasBind);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class)
+ .setQaaLevel(EaafConstants.EIDAS_LOA_PREFIX + RandomStringUtils.randomAlphabetic(5));
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME,
+ RandomStringUtils.randomAlphabetic(2));
+
+ LocaleContextHolder.resetLocaleContext();
+
+ }
+
+ @Test
+ public void eidMode() throws EaafAuthenticationException {
+ // initialize state
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true);
+
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+
+ // execute
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+ // validate state
+ Assert.assertNotNull("AuthData null", authData);
+ Assert.assertNotNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class));
+ Assert.assertNotNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+ Assert.assertNotNull("LoA null", authData.getEidasQaaLevel());
+ Assert.assertEquals("testIdentity flag",
+ isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY,
+ ((EidAuthenticationData)authData).getEidStatus());
+
+ String authBlock = authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class);
+ String eidasBind = authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class);
+
+ Assert.assertEquals("authBlock not equal", this.authBlock, authBlock);
+ Assert.assertEquals("eidasBind not equal", this.eidasBind, eidasBind);
+ Assert.assertEquals("piiTransactionId",
+ authData.getGenericData(ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, String.class),
+ this.pendingReq.getUniquePiiTransactionIdentifier());
+ Assert.assertNotNull("assertion validTo", authData.getSsoSessionValidTo());
+ Assert.assertEquals("LoA", pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel(),
+ authData.getEidasQaaLevel());
+ Assert.assertEquals("EID-ISSUING-NATION",
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME),
+ authData.getCiticenCountryCode());
+
+ Assert.assertNull("bPK", authData.getBpk());
+ Assert.assertNull("bPKType", authData.getBpkType());
+ Assert.assertNull("FamilyName", authData.getFamilyName());
+ Assert.assertNull("GivenName", authData.getGivenName());
+ Assert.assertNull("DateOfBirth", authData.getDateOfBirth());
+ Assert.assertNull("baseId", authData.getIdentificationValue());
+ Assert.assertNull("baseIdType", authData.getIdentificationType());
+ Assert.assertNull("IDL", authData.getIdentityLink());
+
+ }
+
+ @Test
+ public void moaIdMode() throws EaafAuthenticationException, EaafBuilderException {
+ //initialize state
+ boolean isTestIdentity = RandomUtils.nextBoolean();
+ pendingReq.getSessionData(EidAuthProcessDataWrapper.class).setTestIdentity(isTestIdentity);
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(false);
+ IIdentityLink idl = buildDummyIdl();
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).setIdentityLink(idl);
+
+ //execute
+ IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq);
+
+ //validate state
+ Assert.assertNotNull("AuthData null", authData);
+ Assert.assertNull("authBlock null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_SZR_AUTHBLOCK, String.class));
+ Assert.assertNull("eidasBind null", authData.getGenericData(MsEidasNodeConstants.AUTH_DATA_EIDAS_BIND, String.class));
+ Assert.assertNull("piiTransactionId",
+ authData.getGenericData(ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, String.class));
+
+ Assert.assertEquals("testIdentity flag",
+ isTestIdentity ? EidIdentityStatusLevelValues.TESTIDENTITY : EidIdentityStatusLevelValues.IDENTITY,
+ ((EidAuthenticationData)authData).getEidStatus());
+
+ Assert.assertNotNull("assertion validTo", authData.getSsoSessionValidTo());
+ Assert.assertNotNull("LoA null", authData.getEidasQaaLevel());
+ Assert.assertEquals("LoA", pendingReq.getSessionData(AuthProcessDataWrapper.class).getQaaLevel(),
+ authData.getEidasQaaLevel());
+ Assert.assertEquals("EID-ISSUING-NATION",
+ pendingReq.getSessionData(AuthProcessDataWrapper.class).getGenericDataFromSession(
+ PvpAttributeDefinitions.EID_ISSUING_NATION_NAME),
+ authData.getCiticenCountryCode());
+
+ Assert.assertEquals("FamilyName", idl.getFamilyName(), authData.getFamilyName());
+ Assert.assertEquals("GivenName", idl.getGivenName(), authData.getGivenName());
+ Assert.assertEquals("DateOfBirth", idl.getDateOfBirth(), authData.getDateOfBirth());
+ Assert.assertEquals("bPK",
+ BpkBuilder.generateAreaSpecificPersonIdentifier(
+ idl.getIdentificationValue(), EaafConstants.URN_PREFIX_CDID + "XX").getFirst(),
+ authData.getBpk());
+ Assert.assertEquals("bPKType", EaafConstants.URN_PREFIX_CDID + "XX", authData.getBpkType());
+ Assert.assertNotNull("IDL", authData.getIdentityLink());
+
+
+ }
+
+ private IIdentityLink buildDummyIdl() {
+ return new IIdentityLink() {
+
+ String familyName = RandomStringUtils.randomAlphabetic(10);
+ String givenName = RandomStringUtils.randomAlphabetic(10);
+ String dateOfBirth = "1955-02-03";
+ String baseId = RandomStringUtils.randomAlphanumeric(20);
+ String saml2Serialized = RandomStringUtils.randomAlphanumeric(150);
+
+
+
+ @Override
+ public void setSamlAssertion(Element arg0) throws TransformerException, IOException {
+
+ }
+
+ @Override
+ public void setPublicKey(PublicKey[] arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setPrPerson(Element arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIssueInstant(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIdentificationValue(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIdentificationType(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setGivenName(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setFamilyName(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setDsigReferenceTransforms(Element[] arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setDateOfBirth(String arg0) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getSerializedSamlAssertion() {
+ return this.saml2Serialized;
+ }
+
+ @Override
+ public Element getSamlAssertion() {
+ IIdentityLink fullIdl;
+ try {
+ fullIdl = new SimpleIdentityLinkAssertionParser(
+ AuthenticationDataBuilderTest.class.getResourceAsStream("/data/test_idl_1.xml")).parseIdentityLink();
+ return fullIdl.getSamlAssertion();
+
+ } catch (EaafParserException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public PublicKey[] getPublicKey() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Element getPrPerson() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Date getIssueInstantDate() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIssueInstant() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getIdentificationValue() {
+ return this.baseId;
+ }
+
+ @Override
+ public String getIdentificationType() {
+ return EaafConstants.URN_PREFIX_BASEID;
+ }
+
+ @Override
+ public String getGivenName() {
+ return this.givenName;
+ }
+
+ @Override
+ public String getFamilyName() {
+ return this.familyName;
+ }
+
+ @Override
+ public Element[] getDsigReferenceTransforms() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getDateOfBirth() {
+ return this.dateOfBirth;
+
+ }
+ };
+ }
+
+}
diff --git a/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties b/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties
new file mode 100644
index 00000000..991036fe
--- /dev/null
+++ b/core_common_webapp/src/test/resources/config/junit_config_1_springboot.properties
@@ -0,0 +1,113 @@
+## 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=http://localhost:40900/mockup
+
+## 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
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
+
diff --git a/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties b/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties
new file mode 100644
index 00000000..de887fe6
--- /dev/null
+++ b/core_common_webapp/src/test/resources/config/junit_config_2_springboot.properties
@@ -0,0 +1,113 @@
+## 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
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
diff --git a/core_common_webapp/src/test/resources/config/junit_config_3.properties b/core_common_webapp/src/test/resources/config/junit_config_3.properties
new file mode 100644
index 00000000..b4de5aa9
--- /dev/null
+++ b/core_common_webapp/src/test/resources/config/junit_config_3.properties
@@ -0,0 +1,148 @@
+## 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
+
+##Monitoring
+eidas.ms.monitoring.eIDASNode.metadata.url=
+
+
+##Specific logger configuration
+eidas.ms.technicallog.write.MDS.into.techlog=true
+eidas.ms.revisionlog.write.MDS.into.revisionlog=true
+eidas.ms.revisionlog.logIPAddressOfUser=true
+
+##Directory for static Web content
+eidas.ms.webcontent.static.directory=webcontent/
+eidas.ms.webcontent.templates=templates/
+eidas.ms.webcontent.properties=properties/messages
+eidas.ms.webcontent.templates.countryselection=countrySelection.html
+
+## extended validation of pending-request Id's
+eidas.ms.core.pendingrequestid.maxlifetime=300
+eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256
+eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret
+
+## eIDAS Ref. Implementation connector ###
+eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector
+eidas.ms.auth.eIDAS.node_v2.forward.endpoint=
+eidas.ms.auth.eIDAS.node_v2.forward.method=POST
+eidas.ms.auth.eIDAS.node_v2.countrycode=AT
+eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.*
+eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true
+eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true
+
+eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/substantial
+
+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=
+eidas.ms.auth.eIDAS.szrclient.timeout.connection=15
+eidas.ms.auth.eIDAS.szrclient.timeout.response=30
+eidas.ms.auth.eIDAS.szrclient.params.vkz=
+
+eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false
+
+
+#Raw eIDAS Id data storage
+eidas.ms.auth.eIDAS.szrclient.workarounds.eidmapping.revisionlog.active=true
+
+eidas.ms.auth.eIDAS.szrclient.params.setPlaceOfBirthIfAvailable=true
+eidas.ms.auth.eIDAS.szrclient.params.setBirthNameIfAvailable=true
+
+eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true
+eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=true
+
+##without mandates
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.onlynatural.3=DateOfBirth,true
+
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.4=PlaceOfBirth,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.5=BirthName,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.6=Gender,false
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.de.onlynatural.7=CurrentAddress,false
+
+##with mandates ---- NOT FULLY SUPPORTED AT THE MOMENT -----
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.0=PersonIdentifier,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.1=FamilyName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.2=FirstName,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.3=DateOfBirth,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.4=LegalPerson,true
+eidas.ms.auth.eIDAS.node_v2.attributes.requested.representation.5=LegalName,true
+
+
+## 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=
+eidas.ms.pvp2.key.metadata.password=
+eidas.ms.pvp2.key.signing.alias=
+eidas.ms.pvp2.key.signing.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=
+eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks
+eidas.ms.sp.0.pvp2.metadata.truststore.password=password
+eidas.ms.sp.0.newEidMode=true
+
+#eidas.ms.sp.0.friendlyName=
+#eidas.ms.sp.0.pvp2.metadata.url=
+#eidas.ms.sp.0.policy.allowed.requested.targets=.*
+#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false
+
+
+
+#### eIDAS ms-specific Proxy-Service configuration
+eidas.ms.auth.eIDAS.node_v2.proxy.entityId=ownSpecificProxy
+eidas.ms.auth.eIDAS.node_v2.proxy.forward.endpoint=http://eidas.proxy/endpoint
+
+
+## PVP2 S-Profile communication with ID Austria System
+# EntityId and optional metadata of ID Austria System
+eidas.ms.modules.idaustriaauth.idp.entityId=http://junit.idaustria.at/idp
+#eidas.ms.modules.idaustriaauth.idp.metadataUrl=http://junit.idaustria.at/idp/metadata
+
+# SAML2 client configuration
+eidas.ms.modules.idaustriaauth.keystore.type=jks
+#eidas.ms.modules.idaustriaauth.keystore.name=
+eidas.ms.modules.idaustriaauth.keystore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.keystore.password=password
+eidas.ms.modules.idaustriaauth.metadata.sign.alias=meta
+eidas.ms.modules.idaustriaauth.metadata.sign.password=password
+eidas.ms.modules.idaustriaauth.request.sign.alias=sig
+eidas.ms.modules.idaustriaauth.request.sign.password=password
+eidas.ms.modules.idaustriaauth.response.encryption.alias=enc
+eidas.ms.modules.idaustriaauth.response.encryption.password=password
+
+# TrustStore to validate SAML2 metadata from ID Austria
+eidas.ms.modules.idaustriaauth.truststore.type=jks
+eidas.ms.modules.idaustriaauth.truststore.name=
+eidas.ms.modules.idaustriaauth.truststore.path=keys/junit_test.jks
+eidas.ms.modules.idaustriaauth.truststore.password=password
+
+
+
+##only for advanced config
+eidas.ms.configuration.sp.disableRegistrationRequirement=
+eidas.ms.configuration.restrictions.baseID.spTransmission=
+eidas.ms.configuration.auth.default.countrycode=
+eidas.ms.configuration.pvp.scheme.validation=
+eidas.ms.configuration.pvp.enable.entitycategories=
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/config/log4j.properties b/core_common_webapp/src/test/resources/config/log4j.properties
new file mode 100644
index 00000000..4426ea7e
--- /dev/null
+++ b/core_common_webapp/src/test/resources/config/log4j.properties
@@ -0,0 +1,54 @@
+# commons-logging setup
+org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
+
+# define log4j root loggers
+log4j.rootLogger=warn,stdout, console
+
+log4j.logger.at.gv.egiz.eidas.specific=info, msnode
+log4j.logger.at.gv.egiz.eidas.specific.connector.logger.RevisionLogger=info, reversion
+log4j.logger.at.gv.egiz.eidas.specific.connector.logger.StatisticLogger=info, statistic
+log4j.logger.eu.eidas=info, EIDASNODE
+
+log4j.additivity.at.gv.egiz.eidas.specific=false
+log4j.additivity.at.gv.egiz.eidas.specific.connector.logger.RevisionLogger=false
+log4j.additivity.at.gv.egiz.eidas.specific.connector.logger.StatisticLogger=false
+log4j.additivity.eu.eidas=false
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n
+
+log4j.appender.stdout=org.apache.log4j.RollingFileAppender
+log4j.appender.stdout.File=${catalina.base}/logs/console.log
+log4j.appender.stdout.MaxFileSize=10000KB
+log4j.appender.stdout.MaxBackupIndex=9999
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.msnode=org.apache.log4j.RollingFileAppender
+log4j.appender.msnode.File=${catalina.base}/logs/eidas-ms-reversion.log
+log4j.appender.msnode.MaxFileSize=10000KB
+log4j.appender.msnode.MaxBackupIndex=9999
+log4j.appender.msnode.layout=org.apache.log4j.PatternLayout
+log4j.appender.msnode.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.reversion=org.apache.log4j.RollingFileAppender
+log4j.appender.reversion.File=${catalina.base}/logs/eidas-ms-reversion.log
+log4j.appender.reversion.MaxFileSize=10000KB
+log4j.appender.reversion.MaxBackupIndex=9999
+log4j.appender.reversion.layout=org.apache.log4j.PatternLayout
+log4j.appender.reversion.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
+
+log4j.appender.statistic=org.apache.log4j.RollingFileAppender
+log4j.appender.statistic.File=${catalina.base}/logs/eidas-ms-statistic.log
+log4j.appender.statistic.MaxFileSize=10000KB
+log4j.appender.statistic.MaxBackupIndex=9999
+log4j.appender.statistic.layout=org.apache.log4j.PatternLayout
+log4j.appender.statistic.layout.ConversionPattern=%m%n
+
+log4j.appender.EIDASNODE=org.apache.log4j.RollingFileAppender
+log4j.appender.EIDASNODE.File=${catalina.base}/logs/eIDAS_node.log
+log4j.appender.EIDASNODE.MaxFileSize=10000KB
+log4j.appender.EIDASNODE.MaxBackupIndex=9999
+log4j.appender.EIDASNODE.layout=org.apache.log4j.PatternLayout
+log4j.appender.EIDASNODE.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/data/metadata_valid.xml b/core_common_webapp/src/test/resources/data/metadata_valid.xml
new file mode 100644
index 00000000..06e1e785
--- /dev/null
+++ b/core_common_webapp/src/test/resources/data/metadata_valid.xml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=
+
+
+ PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==
+
+
+ MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=
+
+
+
+
+
+
+
+ MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN
+MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw
+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC
+LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG
+SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh
+ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L
+
+
+
+
+
+
+ MIIDKzCCAhMCBFrxKO4wDQYJKoZIhvcNAQELBQAwWjELMAkGA1UEBhMCQVQxDTALBgNVBAoMBEVH
+SVoxGDAWBgNVBAsMD2RlbW8uZWdpei5ndi5hdDEiMCAGA1UEAwwZTU9BLUlEIElEUCAoVGVzdC1W
+ZXJzaW9uKTAeFw0xODA1MDgwNDM0NTRaFw0yMTAxMzEwNDM0NTRaMFoxCzAJBgNVBAYTAkFUMQ0w
+CwYDVQQKDARFR0laMRgwFgYDVQQLDA9kZW1vLmVnaXouZ3YuYXQxIjAgBgNVBAMMGU1PQS1JRCBJ
+RFAgKFRlc3QtVmVyc2lvbikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCaFnqoaYoq
+UptenemC6FiVDg5F2hEjpjix8+ow6/6QhUl2cPOS0uwZHaIvwT/RVbJ9CPdil6+11qaCPfZ+FoY+
+M+ke7TRd2RS1DqFbe1KC0imEnwemyLQrYe5Pm7DNcaY/kHTTq+k0eeGbYH0U/Iopyi0VuN5OWl4F
+Vg45pf7knhXkaimItdjnCXnKcYM91mmltCf6TDgUrz7US7PmgvinnhfBgdITAT4GRr4ehliT+/jt
+1OzHEyWRHanBGIpXNeZNqxgnpnGtaDh4JZuYR8qfH+GRK6dtW2ziej6rGIiUElGVCkXsohgxMNzq
+nWeD9JT8+yyp1XZlyQf+IxhhESQLAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAIFejAFQepaEl/kC
+VLvidMR+MXq5LCGHthUiI6eDTQZ+H7lZdHlj547XwEdX15b6Md3h7eSJ4hwlfV4go/0FaoLPzvVq
+itwtYY5htywB3B6ZV34Eyi6C59Gl34XrV8CWxH4KKwLsVAjAy+/p/Xh0q2pzSBkeOChzBMBkjmyc
+2Ue4MEKdL9guzp6+Yc/HL/phHAKYapkVyFwvsdqWOgyRzxAHINko8ExImMMB3xB5a52kfqLcui5O
+fzEhjwLFJaGBMmFCmFGGOUwtIvl/6ZQ2LLzOE9+giVK9WsIgH11Pu+ejPFAbXf8cf4oWhbAfTkiy
+4jpXrp77JXFRSDWddb0yePc=
+
+
+
+ urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+
+
+
+ Default Service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ EGIZ
+ E-Government Innovationszentrum
+ http://www.egiz.gv.at
+
+
+ E-Government Innovationszentrum
+ Lenz
+ Thomas
+ thomas.lenz@egiz.gv.at
+ +43 316 873 5525
+
+
diff --git a/core_common_webapp/src/test/resources/data/test_idl_1.xml b/core_common_webapp/src/test/resources/data/test_idl_1.xml
new file mode 100644
index 00000000..8151468b
--- /dev/null
+++ b/core_common_webapp/src/test/resources/data/test_idl_1.xml
@@ -0,0 +1,46 @@
+
+
+
+
+ urn:oasis:names:tc:SAML:1.0:cm:sender-vouches
+
+ AT/CZ/xWE0vFWarzpzSL4LYlpst9b6vg0=urn:publicid:gv.at:eidasid+AT+CZXXXMaria-Theresia KunigundaXXXHabsburg-Lothringen1980-02-29
+
+
+
+ 1BFOitiQUc1lAHDGksneXWZGKGaFBcu03HEiIFsjHjNt/IfRZ4IzqHotUKItxnCdNtsFc1MkMJg+
+g0AXHsuU6MNgcbcXPaPfmHp+8+BJh+amDF3FnAN4ceG8oFAGVEZteOgfdWk1r5RQ2SK+0PuXPuLp
+Tee7IzXtksReZkVEadUCxn/hiRXZa0dABgkFe3kSXbDr5tKXOF0FCtLKhZBI9z+NbX+aTSKOmAOq
+4jyymoo5EP3L+iPecrUwHijD0Bm89h1JjxP521fkYe3Si+0J40okrmCCQHBr+IzB1uX98pKhvs7X
+6rPjOJ6lBwP7XjK7D128P/cg4eH6v58cCfbLcQ==AQAB
+
+E+BXH0C2F6EYHjdJrOUKr+DsKT8=Hvj40m9ridp2HOz81MTAqzf0q+sZC5YeKpJP43eK5G1HNH1/DNGU/r/6IVPibU9Y
+YGYJoXpznxRFibEQ6dFCHAaNPyADmdGHyJSWryI5ypAap4Y8MJnaUGSWY49IZbht
+PjfKWB2jUNzj1T2u6ebIifAThAK8ZqIE+e5uaR+qrrLicxIhXcSZoyScbKxMuT1Q
+p6zNsNBOHujbVAfKFUE8WmGInyvuoDgerUrA0XstWWg2M9ghytcDJwZpTYwXvmmo
+GV47ue0ITrtM+QqWVbt+dHO8369JFnGQ9h/6h/4j9iyNuxfG7u/EyHQiSuy0+FP8
+1lkLsg1YX+2pN0HElyXVqw==MIIEqzCCBBSgAwIBAgIHANux81oNezANBgkqhkiG9w0BAQUFADBAMSIwIAYDVQQD
+ExlJQUlLIFRlc3QgSW50ZXJtZWRpYXRlIENBMQ0wCwYDVQQKEwRJQUlLMQswCQYD
+VQQGEwJBVDAeFw0xMzA5MjcwNTMzMzdaFw0yMzA5MjcwNTMzMzdaMIHkMQswCQYD
+VQQGEwJBVDENMAsGA1UEBxMER3JhejEmMCQGA1UEChMdR3JheiBVbml2ZXJzaXR5
+IG9mIFRlY2hub2xvZ3kxSDBGBgNVBAsTP0luc3RpdHV0ZSBmb3IgQXBwbGllZCBJ
+bmZvcm1hdGlvbiBQcm9jZXNzaW5nIGFuZCBDb21tdW5pY2F0aW9uczEUMBIGA1UE
+BBMLTU9BLVNTIFRlc3QxGDAWBgNVBCoTD0VHSVogVGVzdHBvcnRhbDEkMCIGA1UE
+AxMbRUdJWiBUZXN0cG9ydGFsIE1PQS1TUyBUZXN0MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAuDjOyf+mY+oQL2FQzzuaiC8C23vVKbq/n2Zi7BqSibZH
+mtqMJfmj4pT+hWSNHvVvWsaxFcx4KeNqdCMzwnw1r4P3Sf+2o5uFku5KHEMLMokR
+yYQG9VqY/KkB94ye7Pv6zT8gvKqxGFg96UamECep4swPaSZrA8AOER5WAtyGDzKI
+Tz+a5zfFaTXDoba7f98PCWR96yKiFjVOhzp38WVz4VJgz+b8ZSY7Xsv5Kn7DXjOL
+STX4MevFLki3rFPup3+4vGToaMBW3PEj67HXBdqR855Le6+E6rVxORqsXqlVwhsI
+6nuS0CO2LWYmBNR1IB0mXteeYH/HfxvuZc+7yDjdPQIDAQABo4IBhDCCAYAwDgYD
+VR0PAQH/BAQDAgbAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEmcH6VY4BG1EAGB
+TLoNR9vH/g6yMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9jcmxzL0lBSUtUZXN0X0ludGVybWVkaWF0ZUNBLmNybDCBqgYI
+KwYBBQUHAQEEgZ0wgZowSgYIKwYBBQUHMAGGPmh0dHA6Ly9jYS5pYWlrLnR1Z3Jh
+ei5hdC9jYXBzby9PQ1NQP2NhPUlBSUtUZXN0X0ludGVybWVkaWF0ZUNBMEwGCCsG
+AQUFBzAChkBodHRwOi8vY2EuaWFpay50dWdyYXouYXQvY2Fwc28vY2VydHMvSUFJ
+S1Rlc3RfSW50ZXJtZWRpYXRlQ0EuY2VyMCEGA1UdEQQaMBiBFnRob21hcy5sZW56
+QGVnaXouZ3YuYXQwHwYDVR0jBBgwFoAUaKJeEdreL4BrRES/jfplNoEkp28wDQYJ
+KoZIhvcNAQEFBQADgYEAlFGjUxXLs7SAT8NtXSrv2WrjlklaRnHTFHLQwyVo8JWb
+gvRkHHDUv2o8ofXUY2R2WJ38dxeDoccgbXrJb/Qhi8IY7YhCwv/TuIZDisyAqo8W
+ORKSip/6HWlGCSR/Vgoet1GtCmF0FoUxFUIGSAuQ2yyt4fIzt5GJrU1X5ujjI1w=
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml b/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml
new file mode 100644
index 00000000..bf2c78ac
--- /dev/null
+++ b/core_common_webapp/src/test/resources/spring/SpringTest-context_basic_test.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml b/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml
new file mode 100644
index 00000000..5a37b98f
--- /dev/null
+++ b/core_common_webapp/src/test/resources/spring/SpringTest-context_healthcheck.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml b/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml
new file mode 100644
index 00000000..966d317a
--- /dev/null
+++ b/core_common_webapp/src/test/resources/spring/SpringTest-context_simple_storage.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml b/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml
new file mode 100644
index 00000000..e66ac987
--- /dev/null
+++ b/core_common_webapp/src/test/resources/spring/SpringTest_core.beans.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml b/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml
new file mode 100644
index 00000000..2da610f0
--- /dev/null
+++ b/core_common_webapp/src/test/resources/spring/SpringTest_core_config.beans.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3