diff options
Diffstat (limited to 'connector')
55 files changed, 3436 insertions, 816 deletions
diff --git a/connector/checks/spotbugs-exclude.xml b/connector/checks/spotbugs-exclude.xml new file mode 100644 index 00000000..281e3796 --- /dev/null +++ b/connector/checks/spotbugs-exclude.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<FindBugsFilter> + <Match> + <!-- Write only application status into response. Should be removed if we switch to Spring Actuator --> + <Class name="at.asitplus.eidas.specific.connector.controller.MonitoringController" /> + <Method name="startSingleTests" /> + <Bug pattern="XSS_SERVLET" /> + </Match> + <Match> + <!-- CSFR protection is implemented by pendingRequestId that is an one-time token + Endpoint for Metadata generation can be unrestrected by design --> + <OR> + <Class name="at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController" /> + <Class name="at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint" /> + </OR> + <OR> + <Method name="performGenericAuthenticationProcess" /> + <Method name="pvpMetadataRequest" /> + </OR> + <Bug pattern="SPRING_CSRF_UNRESTRICTED_REQUEST_MAPPING" /> + </Match> + <Match> + <!-- Path to application configuration is trusted --> + <Class name="at.asitplus.eidas.specific.connector.MsSpecificSpringBootApplicationContextInitializer" /> + <Bug pattern="PATH_TRAVERSAL_IN" /> + </Match> +</FindBugsFilter> diff --git a/connector/pom.xml b/connector/pom.xml index 6621fb0f..36a6d9df 100644 --- a/connector/pom.xml +++ b/connector/pom.xml @@ -12,7 +12,7 @@ <groupId>at.asitplus.eidas.ms_specific</groupId> <artifactId>ms_specific_connector</artifactId> <packaging>war</packaging> - <name>Connector Maven Webapp</name> + <name>MS-specific eIDAS Service</name> <url>http://maven.apache.org</url> <dependencies> @@ -33,12 +33,6 @@ <dependency> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_module_pvp2_idp</artifactId> - <exclusions> - <exclusion> - <groupId>org.slf4j</groupId> - <artifactId>log4j-over-slf4j</artifactId> - </exclusion> - </exclusions> </dependency> <dependency> <groupId>at.asitplus.eidas.ms_specific</groupId> @@ -49,7 +43,25 @@ <artifactId>authmodule-eIDAS-v2</artifactId> </dependency> - <!-- Third party libs --> + <!-- Third party libs --> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-actuator</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <exclusions> + <exclusion> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-tomcat</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>de.codecentric</groupId> + <artifactId>spring-boot-admin-starter-client</artifactId> + </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> @@ -67,18 +79,13 @@ <artifactId>slf4j-api</artifactId> </dependency> <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - </dependency> - <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> </dependency> - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>javax.servlet-api</artifactId> - <scope>provided</scope> - </dependency> + <dependency> + <groupId>org.hibernate.validator</groupId> + <artifactId>hibernate-validator</artifactId> + </dependency> <!-- Testing --> @@ -93,6 +100,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>at.gv.egiz.eaaf</groupId> <artifactId>eaaf_core_utils</artifactId> <scope>test</scope> @@ -104,21 +116,82 @@ <scope>test</scope> <type>test-jar</type> </dependency> - + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf_module_pvp2_sp</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-tomcat</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-springboot-utils</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.github.skjolber</groupId> + <artifactId>mockito-soap-cxf</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + <version>2.0.7</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito2</artifactId> + <version>2.0.7</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.squareup.okhttp3</groupId> + <artifactId>mockwebserver</artifactId> + <scope>test</scope> + </dependency> </dependencies> + + <profiles> + <profile> + <id>default</id> + <activation> + <activeByDefault>true</activeByDefault> + <property> + <name>default</name> + </property> + </activation> + <dependencies> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + </profile> + <profile> + <id>embbededTomcat</id> + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-tomcat</artifactId> + </dependency> + <dependency> + <groupId>at.gv.egiz.eaaf</groupId> + <artifactId>eaaf-springboot-utils</artifactId> + </dependency> + </dependencies> + </profile> + + </profiles> + <build> <finalName>ms_connector</finalName> <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>1.8</source> - <target>1.8</target> - </configuration> - </plugin> - <!-- enable co-existence of testng and junit --> <plugin> <artifactId>maven-surefire-plugin</artifactId> @@ -135,6 +208,24 @@ </plugin> <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <version>2.2.6.RELEASE</version> + <configuration> + <executable>true</executable> + <!-- layout>ZIP</layout --> + </configuration> + <executions> + <execution> + <goals> + <goal>build-info</goal> + <goal>repackage</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <configuration> @@ -156,6 +247,15 @@ </executions> </plugin> + <plugin> + <groupId>com.github.spotbugs</groupId> + <artifactId>spotbugs-maven-plugin</artifactId> + <version>${spotbugs-maven-plugin.version}</version> + <configuration> + <excludeFilterFile>checks/spotbugs-exclude.xml</excludeFilterFile> + </configuration> + </plugin> + </plugins> </build> </project> diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificEidasNodeSpringResourceProvider.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificEidasNodeSpringResourceProvider.java index 6e8e06ef..40ed283b 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificEidasNodeSpringResourceProvider.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificEidasNodeSpringResourceProvider.java @@ -32,11 +32,15 @@ public class MsSpecificEidasNodeSpringResourceProvider implements SpringResource @Override public Resource[] getResourcesToLoad() { - final ClassPathResource msEidasNode = new ClassPathResource("/specific_eIDAS_connector.beans.xml", - MsSpecificEidasNodeSpringResourceProvider.class); + final ClassPathResource generic = + new ClassPathResource("/applicationContext.xml", MsSpecificEidasNodeSpringResourceProvider.class); + + final ClassPathResource msEidasNode = new ClassPathResource( + "/specific_eIDAS_connector.beans.xml", MsSpecificEidasNodeSpringResourceProvider.class); + final ClassPathResource msEidasNodeStorage = new ClassPathResource( "/specific_eIDAS_connector.storage.beans.xml", MsSpecificEidasNodeSpringResourceProvider.class); - return new Resource[] { msEidasNode, msEidasNodeStorage }; + return new Resource[] { generic, msEidasNode, msEidasNodeStorage }; } @Override diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java new file mode 100644 index 00000000..399d1286 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java @@ -0,0 +1,82 @@ +package at.asitplus.eidas.specific.connector; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Properties; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertiesPropertySource; + +import at.gv.egiz.components.spring.api.SpringBootApplicationContextInitializer; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class MsSpecificSpringBootApplicationContextInitializer extends + SpringBootApplicationContextInitializer { + + private static final String SYSTEMD_PROP_NAME = "eidas.ms.configuration"; + private static final String PATH_FILE_PREFIX = "file:"; + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + String configPath = System.getProperty(SYSTEMD_PROP_NAME); + if (StringUtils.isNotEmpty(configPath)) { + log.debug("Find configuration-source from SystemD Property: '{}' ...", SYSTEMD_PROP_NAME); + if (configPath.startsWith(PATH_FILE_PREFIX)) { + configPath = configPath.substring(PATH_FILE_PREFIX.length()); + + } + injectConfiguration(configPath, applicationContext); + + } else { + log.info("Find NO SystemD Property: '{}' Maybe no configuration available", SYSTEMD_PROP_NAME); + + } + + super.initialize(applicationContext); + + } + + private void injectConfiguration(String configPath, ConfigurableApplicationContext applicationContext) { + InputStream is = null; + try { + Path path = Paths.get(configPath); + if (Files.exists(path)) { + File file = new File(configPath); + Properties props = new Properties(); + is = new FileInputStream(file); + props.load(is); + MutablePropertySources sources = applicationContext.getEnvironment().getPropertySources(); + sources.addFirst(new PropertiesPropertySource(SYSTEMD_PROP_NAME, props)); + log.info("Set configuration-source from SystemD-Property: {}", SYSTEMD_PROP_NAME); + + } else { + log.error("Configuration from SystemD Property: '{}' at Location: {} DOES NOT exist", + SYSTEMD_PROP_NAME, configPath); + + } + + } catch (IOException e) { + log.error("Configuration from SystemD Property: '{}' at Location: {} CAN NOT be loaded", + SYSTEMD_PROP_NAME, configPath, e); + + } finally { + try { + if (is != null) { + is.close(); + + } + } catch (IOException e) { + log.error("Can not close InputStream of configLoader: {}", configPath, e); + + } + } + } +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java new file mode 100644 index 00000000..428f5f56 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java @@ -0,0 +1,105 @@ +package at.asitplus.eidas.specific.connector; + +import org.opensaml.core.config.InitializationException; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.web.context.WebApplicationContext; + +import at.gv.egiz.eaaf.core.api.IStatusMessenger; +import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; +import at.gv.egiz.eaaf.core.impl.logging.SimpleStatusMessager; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@Slf4j +@SpringBootApplication(scanBasePackages = { + "at.asitplus.eidas.specific.connector", + "at.gv.egiz.eaaf.utils.springboot.ajp" + }) +public class SpringBootApplicationInitializer extends SpringBootServletInitializer { + + private static ConfigurableApplicationContext ctx; + + /** + * Starts MS-specific eIDAS-Implementation SpringBoot application. + * + * @param args Starting parameters + * @throws Throwable In case of a start-up error + */ + public static void main(final String[] args) throws Throwable { + try { + log.info("=============== Initializing Spring-Boot context! ==============="); + LogMessageProviderFactory.setStatusMessager(new SimpleStatusMessager()); + final SpringApplication springApp = + new SpringApplication(SpringBootApplicationInitializer.class); + springApp.addInitializers(new MsSpecificSpringBootApplicationContextInitializer()); + + log.info("Bootstrap openSAML .... "); + EaafOpenSaml3xInitializer.eaafInitialize(); + + log.debug("Run SpringBoot initialization process ... "); + ctx = springApp.run(args); + + // initialize status messenger + LogMessageProviderFactory.setStatusMessager(ctx.getBean(IStatusMessenger.class)); + + log.info("Initialization of MS-specific eIDAS-Implementation finished."); + + } catch (final Throwable e) { + log.error("MS-specific eIDAS-Implementation initialization FAILED!", e); + throw e; + + } + + } + + + protected SpringApplicationBuilder createSpringApplicationBuilder() { + try { + log.info("Bootstrap openSAML .... "); + EaafOpenSaml3xInitializer.eaafInitialize(); + + } catch (InitializationException | ComponentInitializationException e) { + throw new RuntimeException(e); + + } + + SpringApplicationBuilder builder = new SpringApplicationBuilder(); + builder.initializers(new MsSpecificSpringBootApplicationContextInitializer()); + return builder; + + } + + protected WebApplicationContext run(SpringApplication application) { + WebApplicationContext internalContext = (WebApplicationContext) application.run(); + + // initialize status messenger + LogMessageProviderFactory.setStatusMessager(internalContext.getBean(IStatusMessenger.class)); + + log.info("Initialization of MS-specific eIDAS-Implementation finished."); + + return internalContext; + } + + /** + * Stops SpringBoot application of MS-specific eIDAS-Implementation. + * + */ + public static void exit() { + if (ctx != null) { + log.info("Stopping SpringBoot application ... "); + SpringApplication.exit(ctx, () -> 0); + ctx = null; + + } else { + log.info("No SpringBoot context. Nothing todo"); + + } + + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java new file mode 100644 index 00000000..e884b5c6 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java @@ -0,0 +1,170 @@ +package at.asitplus.eidas.specific.connector; + +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<ContextClosedEvent>, 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<String, IDestroyableObject> objectsToDestroy = + context.getBeansOfType(IDestroyableObject.class); + internalIDestroyableObject(objectsToDestroy); + log.info("Object cleanUp complete"); + + log.debug("Stopping Spring Thread-Pools ... "); + // shut-down task schedulers + final Map<String, ThreadPoolTaskScheduler> schedulers = + context.getBeansOfType(ThreadPoolTaskScheduler.class); + internalThreadPoolTaskScheduler(schedulers); + + // shut-down task executors + final Map<String, ThreadPoolTaskExecutor> executers = + context.getBeansOfType(ThreadPoolTaskExecutor.class); + internalThreadPoolTaskExecutor(executers); + log.debug("Spring Thread-Pools stopped"); + + + //clean-up eIDAS node + Map<String, IgniteInstanceInitializerSpecificCommunication> nodeIgnite = + context.getBeansOfType(IgniteInstanceInitializerSpecificCommunication.class); + log.info("Find #{} Apache Ignite instances from eIDAS Ref. impl.", nodeIgnite.size()); + for (Entry<String, IgniteInstanceInitializerSpecificCommunication> 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<String, ThreadPoolTaskExecutor> 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<String, ThreadPoolTaskScheduler> schedulers) { + log.trace("Stopping #{} task-schedulers", schedulers.size()); + + } + + private void internalIDestroyableObject(final Map<String, IDestroyableObject> objectsToDestroy) { + if (objectsToDestroy != null) { + final Iterator<Entry<String, IDestroyableObject>> interator = + objectsToDestroy.entrySet().iterator(); + while (interator.hasNext()) { + final Entry<String, IDestroyableObject> 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/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java deleted file mode 100644 index 417828a6..00000000 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2018 A-SIT Plus GmbH - * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, - * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "License"); - * You may not use this work except in compliance with the License. - * You may obtain a copy of the License at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.asitplus.eidas.specific.connector; - -import java.util.Arrays; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.context.support.GenericApplicationContext; -import org.springframework.core.io.ClassPathResource; -import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.ContextLoaderListener; -import org.springframework.web.context.request.RequestContextListener; -import org.springframework.web.context.support.GenericWebApplicationContext; -import org.springframework.web.context.support.ServletContextResource; -import org.springframework.web.servlet.DispatcherServlet; - -import at.gv.egiz.components.spring.api.SpringLoader; -import at.gv.egiz.eaaf.core.api.IStatusMessenger; -import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; - -/** - * Web application initializer. - * - * @author Thomas Lenz - */ -public class SpringInitializer implements WebApplicationInitializer { - - private static final Logger log = LoggerFactory.getLogger(SpringInitializer.class); - - private String[] rootServletContexts = null; - private String[] servletContexts = null; - - /** - * Application specific Spring initializer. - * - */ - public SpringInitializer() { - this.rootServletContexts = null; - this.servletContexts = new String[] { - "/applicationContext.xml", - - }; - } - - /* - * (non-Javadoc) - * - * @see - * org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet. - * ServletContext) - */ - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - try { - log.info("=============== Loading Config Root Context! ==============="); - final ApplicationContext cfgRootContext = - new ClassPathXmlApplicationContext(new String[] { - "/applicationContext.xml" - }); - - log.info("=============== Loading Root Context! ==============="); - final GenericWebApplicationContext rootContext = new GenericWebApplicationContext(); - rootContext.setServletContext(servletContext); - rootContext.setParent(cfgRootContext); - - log.info("Spring-context was initialized with active profiles: {}", - Arrays.asList(rootContext.getEnvironment().getActiveProfiles())); - - log.info("=============== Loading Local Contexts! ==============="); - final XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader( - rootContext); - if (rootServletContexts != null) { - for (final String rootServletContext : rootServletContexts) { - log.debug("Loading: " + rootServletContext); - xmlReader.loadBeanDefinitions(new ServletContextResource( - servletContext, rootServletContext)); - } - } - // Manage the lifecycle of the root application context - servletContext.addListener(new ContextLoaderListener(rootContext)); - - // log.debug("Beans after logAMQP in {}", rootContext); - // dumpBeanDefinitions(rootContext); - - log.info("=============== Loading SPI Context! ==============="); - log.debug("Loading modules and components"); - SpringLoader.loadSpringServices(rootContext); - - log.trace("Beans after SPI in " + rootContext); - dumpBeanDefinitions(rootContext); - - log.debug("Loading servlet config in " + rootContext); - if (servletContexts != null) { - for (final String servletContextString : servletContexts) { - xmlReader.loadBeanDefinitions(new ClassPathResource(servletContextString, SpringInitializer.class)); - } - - } - - log.debug("Refreshing context " + rootContext); - rootContext.refresh(); - - log.info("=============== Register Dispatcher Servlet! ==============="); - - log.trace("Final Beans in " + rootContext); - dumpBeanDefinitions(rootContext); - - log.info("Registering dispatcher configuration"); - final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", - new DispatcherServlet(rootContext)); - if (dispatcher != null) { - dispatcher.setLoadOnStartup(1); - dispatcher.addMapping("/"); - dispatcher.setAsyncSupported(true); - - } else { - log.error("Failed to register dispatcher server in servlet context!"); - } - - log.info("=============== Register RequestContextListener! ==============="); - servletContext.addListener(new RequestContextListener()); - - // initialize status messenger - LogMessageProviderFactory.setStatusMessager(rootContext.getBean(IStatusMessenger.class)); - - log.info("Bootstrap openSAML .... "); - EaafOpenSaml3xInitializer.eaafInitialize(); - - log.info("Seed random number generator ... "); - Random.seedRandom(); - - log.info("Initialization of MS-specific eIDAS-connector finished."); - - } catch (final Throwable e) { - log.error("MS-specific eIDAS-connector initialization FAILED!", e); - - } - - } - - private void dumpBeanDefinitions(GenericApplicationContext context) { - log.trace("Registered Bean in context " + context.toString()); - - final String[] registeredBeans = context.getBeanDefinitionNames(); - for (final String registeredBean : registeredBeans) { - final BeanDefinition beanDefinition = context - .getBeanDefinition(registeredBean); - log.trace(registeredBean + " -> " + beanDefinition.getBeanClassName()); - - } - - log.trace("Registered Bean in context --" + context); - } -} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java index be9f8862..1833f377 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/attributes/AuthBlockAttributeBuilder.java @@ -22,6 +22,9 @@ package at.asitplus.eidas.specific.connector.attributes; import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME; import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_NAME; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + import org.apache.commons.lang3.StringUtils; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; @@ -48,7 +51,8 @@ public class AuthBlockAttributeBuilder implements IPvpAttributeBuilder { String authBlock = authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class); if (StringUtils.isNotEmpty(authBlock)) { - return g.buildStringAttribute(EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME, EID_AUTHBLOCK_SIGNED_NAME, authBlock); + return g.buildStringAttribute(EID_AUTHBLOCK_SIGNED_FRIENDLY_NAME, EID_AUTHBLOCK_SIGNED_NAME, + Base64.getEncoder().encodeToString(authBlock.getBytes(StandardCharsets.UTF_8))); } else { throw new UnavailableAttributeException(EID_AUTHBLOCK_SIGNED_NAME); diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java index 13cceafb..c41660ce 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/builder/AuthenticationDataBuilder.java @@ -25,70 +25,63 @@ package at.asitplus.eidas.specific.connector.builder; import java.util.Date; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import org.w3c.dom.DOMException; import at.asitplus.eidas.specific.connector.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.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.EaafAuthenticationException; import at.gv.egiz.eaaf.core.exceptions.EaafBuilderException; -import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.exceptions.EaafParserException; -import at.gv.egiz.eaaf.core.exceptions.XPathException; 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.auth.builder.AbstractAuthenticationDataBuilder; import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +import lombok.extern.slf4j.Slf4j; @Service("AuthenticationDataBuilder") +@Slf4j public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder { - private static final Logger log = LoggerFactory.getLogger(AuthenticationDataBuilder.class); - + @Override - public IAuthData buildAuthenticationData(IRequest pendingReq) throws EaafAuthenticationException { - - final IAuthProcessDataContainer authProcessData = pendingReq.getSessionData(AuthProcessDataWrapper.class); + protected IAuthData buildDeprecatedAuthData(IRequest pendingReq) throws EaafException { + final IAuthProcessDataContainer authProcessData = + pendingReq.getSessionData(AuthProcessDataWrapper.class); AuthenticationData authData = new AuthenticationData(); - - boolean isEidModeNew = pendingReq.getServiceProviderConfiguration() - .isConfigurationValue(MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE, false); - - if (isEidModeNew) { - authData = (AuthenticationData) super.buildAuthenticationData(pendingReq); - } else { - try { - generateDeprecatedBasicAuthData(authData, pendingReq, authProcessData); - - // set specific informations - authData.setSsoSessionValidTo( - new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000)); - - } catch (EaafBuilderException | EaafParserException - | EaafConfigurationException | XPathException | DOMException e) { - log.warn("Can not build authentication data from auth. process information"); - throw new EaafAuthenticationException("builder.11", new Object[]{e.getMessage()}, e); - - } - } + + //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)); + return authData; - } - - @Override - protected IAuthData buildDeprecatedAuthData(IRequest arg0) throws EaafException { - return new AuthenticationData(); } @Override - protected void buildServiceSpecificAuthenticationData(IAuthData arg0, IRequest arg1) throws EaafException { - // TODO Auto-generated method stub - + protected void buildServiceSpecificAuthenticationData(IAuthData authData, IRequest pendingReq) + throws EaafException { + if (authData instanceof AuthenticationData) { + ((AuthenticationData)authData).setGenericData( + ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, + pendingReq.getUniquePiiTransactionIdentifier()); + log.trace("Inject piiTransactionId: {} into AuthData", pendingReq.getUniquePiiTransactionIdentifier()); + + // set specific informations + ((AuthenticationData)authData).setSsoSessionValidTo( + new Date(new Date().getTime() + MsEidasNodeConstants.DEFAULT_PVP_ASSERTION_VALIDITY * 60 * 1000)); + + + } else { + throw new RuntimeException("Can not inject PiiTransactionId because AuthData is of unknown type: " + + authData.getClass().getName()); + + } + } @Override @@ -100,8 +93,6 @@ public class AuthenticationDataBuilder extends AbstractAuthenticationDataBuilder @Override protected Pair<String, String> buildOAspecificbPK(IRequest pendingReq, AuthenticationData authData) throws EaafBuilderException { - // TODO: check if bPK already exists - return super.buildOAspecificbPK(pendingReq, authData); } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/StaticResourceConfiguration.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/StaticResourceConfiguration.java index 2a10031b..a1e953f1 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/config/StaticResourceConfiguration.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/config/StaticResourceConfiguration.java @@ -24,6 +24,7 @@ package at.asitplus.eidas.specific.connector.config; import java.net.MalformedURLException; +import java.util.List; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -35,11 +36,11 @@ import org.springframework.context.support.ReloadableResourceBundleMessageSource import org.springframework.web.servlet.config.annotation.EnableWebMvc; 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.connector.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; /** @@ -90,43 +91,63 @@ public class StaticResourceConfiguration implements WebMvcConfigurer { } /** - * Internal i18n message source. - * + * Get a message source with only internal message properties. + * + * @param ressourceLocations List of source-locations * @return */ @Bean - public ReloadableResourceBundleMessageSource internalMessageSource() { - final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); + public ReloadableResourceBundleMessageSource internalMessageSource( + @Autowired(required = false) final List<IMessageSourceLocation> 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; } /** - * External i18n message source. - * + * Get full message source with internal and external message-properties files. + * + * @param ressourceLocations List of source-locations * @return */ @Bean - public ReloadableResourceBundleMessageSource messageSource() { - final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); + public ReloadableResourceBundleMessageSource messageSource( + @Autowired(required = false) final List<IMessageSourceLocation> ressourceLocations) { + final ReloadableResourceBundleMessageSource messageSource = + new ReloadableResourceBundleMessageSource(); messageSource.setDefaultEncoding("UTF-8"); - messageSource.setParentMessageSource(internalMessageSource()); + messageSource.setParentMessageSource(internalMessageSource(ressourceLocations)); - final String staticResources = basicConfig.getBasicConfiguration( - MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH); + final String staticResources = basicConfig + .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_PROPERTIES_PATH); try { if (StringUtils.isNotEmpty(staticResources)) { - final String absPath = FileUtils.makeAbsoluteUrl(staticResources, basicConfig - .getConfigurationRootDirectory()); + final String absPath = + FileUtils.makeAbsoluteUrl(staticResources, basicConfig.getConfigurationRootDirectory()); messageSource.setBasename(absPath); - messageSource.setFallbackToSystemLocale(false); } else { log.debug("No Ressourcefolder for dynamic Web content templates"); + } } catch (final MalformedURLException e) { @@ -137,40 +158,28 @@ public class StaticResourceConfiguration implements WebMvcConfigurer { return messageSource; } - + /** - * Cookie based i18n language selector. - * - * @return - */ - @Bean - public CookieLocaleResolver localeResolver() { - final CookieLocaleResolver localeResolver = new CookieLocaleResolver(); - localeResolver.setCookieName("currentLanguage"); - localeResolver.setCookieMaxAge(3600); - return localeResolver; - } - - - /** - * Thymeleaf based template resolver. - * + * 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); + final String staticResources = basicConfig + .getBasicConfiguration(MsEidasNodeConstants.PROP_CONFIG_WEBCONTENT_TEMPLATES_PATH); try { if (StringUtils.isNotEmpty(staticResources)) { - String absPath = FileUtils.makeAbsoluteUrl(staticResources, basicConfig - .getConfigurationRootDirectory()); + 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(); @@ -179,11 +188,12 @@ public class StaticResourceConfiguration implements WebMvcConfigurer { viewResolver.setTemplateMode("HTML"); viewResolver.setCacheable(false); - log.info("Add Ressourcefolder: " + absPath + " for dynamic Web content templates"); + 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) { @@ -191,8 +201,7 @@ public class StaticResourceConfiguration implements WebMvcConfigurer { } - // TODO: implement some backup solution - return null; + throw new RuntimeException("Can NOT initialize HTML template resolver"); } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java deleted file mode 100644 index aa45c836..00000000 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright 2018 A-SIT Plus GmbH - * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, - * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "License"); - * You may not use this work except in compliance with the License. - * You may obtain a copy of the License at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.asitplus.eidas.specific.connector.controller; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.TransformerFactoryConfigurationError; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - -@Controller -public class MonitoringController { - private static final Logger log = LoggerFactory.getLogger(MonitoringController.class); - - private static final String MESSAGE_OK = "OK"; - private static final String MESSAGE_ERROR = "ERROR"; - private static final String MESSAGE_SKIPPED = "SKIPPED"; - - private static final String TEST_STORAGE = "Storage: "; - private static final String TEST_CONFIG = "Config: "; - private static final String TEST_PVPMETADATA = "PVP_metadata: "; - private static final String TEST_EIDASNODEMETADATA = "eIDASNode_metadata: "; - - @Autowired - private ITransactionStorage storage; - @Autowired - private IConfigurationWithSP config; - - @Autowired private IHttpClientFactory httpClientFactory; - - @Autowired - private PvpMetadataBuilder metadatabuilder; - @Autowired - private IPvpMetadataConfigurationFactory configFactory; - private AbstractCredentialProvider pvpIdpCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * - * @param pvpIdpCredentials credential provider - */ - public void setPvpIdpCredentials(AbstractCredentialProvider pvpIdpCredentials) { - this.pvpIdpCredentials = pvpIdpCredentials; - - } - - /** - * Generic exception handling that wrote an error-message to html response. - * - * @param resp Http response object - * @param exception Error - * @throws IOException In case of a html response error. - */ - @ExceptionHandler({ Throwable.class }) - public void genericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { - log.error("Monitoring Servlet receives an error.", exception); - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write("Reason: " - + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage()))); - - } - - /** - * MS-Connector status-monitoring end-point. - * - * @param req http request - * @param resp http response - * @throws IOException In case of a general processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_MONITOR }, - method = { RequestMethod.GET }) - public void startFullTest(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - - try { - testConfig(); - testStorage(); - testPvpMetadata(); - testEidasNodeMetadata(); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(MESSAGE_OK); - - } catch (final Exception e) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write(MESSAGE_ERROR); - - } - - } - - /** - * MS-Connector internal verify monitoring end-point. - * - * @param req http request object - * @param resp http response object - * @throws IOException In case of an internal processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_VERIFY }, - method = { RequestMethod.GET }) - - public void startSingleTests(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String result = StringUtils.EMPTY; - try { - result += testConfig() + "<br>"; - } catch (final Exception e) { - result += e.getMessage() + "<br>"; - } - - try { - result += testStorage() + "<br>"; - } catch (final Exception e) { - result += e.getMessage() + "<br>"; - } - - try { - result += testPvpMetadata() + "<br>"; - } catch (final Exception e) { - result += e.getMessage() + "<br>"; - } - - try { - result += testEidasNodeMetadata() + "<br>"; - } catch (final Exception e) { - result += e.getMessage() + "<br>"; - } - - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(result); - - } - - private String testStorage() throws Exception { - try { - final String key = Random.nextHexRandom16(); - final String value = Random.nextHexRandom16(); - - storage.put(key, value, -1); - final String result = storage.get(key, String.class); - storage.remove(key); - - if (result != null && result.equals(value)) { - return TEST_STORAGE + MESSAGE_OK; - } else { - log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); - } - - } catch (final EaafException e) { - log.warn("Montioring: Can not read/write to storage.", e); - - } - - throw new Exception(TEST_STORAGE + MESSAGE_ERROR); - - } - - private String testConfig() throws Exception { - try { - if (config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) != null - && config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) - .size() > 0) { - return TEST_CONFIG + MESSAGE_OK; - } else { - log.warn("Montioring: Can not read from configuration file."); - } - - } catch (final Exception e) { - log.warn("Montioring: Can not read from configuration file.", e); - } - - throw new Exception(TEST_CONFIG + MESSAGE_ERROR); - - } - - private String testPvpMetadata() throws Exception { - try { - // build metadata - final IPvpMetadataBuilderConfiguration metadataConfig = - configFactory.generateMetadataBuilderConfiguration( - "http://localhost/monitoring", - pvpIdpCredentials); - metadatabuilder.buildPvpMetadata(metadataConfig); - return TEST_PVPMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_PVPMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_PVPMETADATA + MESSAGE_ERROR, e); - - } - - } - - private String testEidasNodeMetadata() throws Exception { - try { - final String urlString = config.getBasicConfiguration( - MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); - if (StringUtils.isEmpty(urlString)) { - log.debug("No eIDASNode metadata URL. Skipping test ... "); - return TEST_EIDASNODEMETADATA + MESSAGE_SKIPPED; - - } - - // create HTTP client - // TODO: update if we switch to openSAML3 - CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); - HttpUriRequest request = new HttpGet(urlString); - - final CloseableHttpResponse respCode = httpClient.execute(request); - if (respCode.getStatusLine().getStatusCode() != 200) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + " HTTP responsecode: " - + respCode); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR); - - } - - // parse metadata - DomUtils.parseXmlNonValidating(respCode.getEntity().getContent()); - - return TEST_EIDASNODEMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR, e); - - } - - } - -} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java new file mode 100644 index 00000000..f160916c --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java @@ -0,0 +1,69 @@ +package at.asitplus.eidas.specific.connector.health; + +import java.io.ByteArrayInputStream; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Triple; +import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EidasNodeMetadataHealthIndicator implements HealthIndicator { + + @Autowired IConfiguration config; + @Autowired IHttpClientFactory httpClientFactory; + + @Override + public Health health() { + try { + final String urlString = config.getBasicConfiguration( + MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); + if (StringUtils.isEmpty(urlString)) { + log.trace("No eIDASNode metadata URL. Skipping test ... "); + return Health.unknown().build(); + + } + + // create HTTP client + CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); + URIBuilder uriBuilder = new URIBuilder(urlString); + HttpUriRequest request = new HttpGet(uriBuilder.build()); + + final Triple<StatusLine, ByteArrayInputStream, ContentType> respCode = httpClient.execute(request, + HttpUtils.bodyStatusCodeResponseHandler()); + if (respCode.getFirst().getStatusCode() != 200) { + log.warn("Monitoring: Get http StatusCode: {} from eIDAS-Node Metadata endpoint", + respCode.getFirst().getStatusCode()); + return Health.down().withDetail("http StatusCode", respCode.getFirst().getStatusCode()).build(); + + } + + // parse metadata + DomUtils.parseXmlNonValidating(respCode.getSecond()); + + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + log.warn("Monitoring: Can not read SAML2 metadata from eIDAS-Node", e); + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/IgniteClusterHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/IgniteClusterHealthIndicator.java new file mode 100644 index 00000000..10517565 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/IgniteClusterHealthIndicator.java @@ -0,0 +1,52 @@ +package at.asitplus.eidas.specific.connector.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/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java new file mode 100644 index 00000000..592231b0 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java @@ -0,0 +1,44 @@ +package at.asitplus.eidas.specific.connector.health; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class Saml2MetadataHealthIndicator implements HealthIndicator { + + @Autowired + private PvpMetadataBuilder metadatabuilder; + @Autowired + private IPvpMetadataConfigurationFactory configFactory; + + @Setter + private AbstractCredentialProvider pvpIdpCredentials; + + @Override + public Health health() { + try { + // build metadata + final IPvpMetadataBuilderConfiguration metadataConfig = + configFactory.generateMetadataBuilderConfiguration( + "http://localhost/monitoring", + pvpIdpCredentials); + metadatabuilder.buildPvpMetadata(metadataConfig); + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java index 86808f01..d3b8116a 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java @@ -26,8 +26,6 @@ package at.asitplus.eidas.specific.connector.processes.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -39,7 +37,6 @@ import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -51,7 +48,6 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; */ @Component("GenerateCountrySelectionFrameTask") public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(GenerateCountrySelectionFrameTask.class); @Autowired ISpringMvcGuiFormBuilder guiBuilder; @@ -77,16 +73,11 @@ public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { guiBuilder.build(request, response, config, "BKU-Selection form"); - } catch (final GuiBuildException e) { - log.warn("Can not build GUI:'BKU-Selection'. Msg:" + e.getMessage()); + } catch (final Exception e) { throw new TaskExecutionException(pendingReq, "Can not build GUI. Msg:" + e.getMessage(), new EaafException("gui.00", new Object[] { e.getMessage() }, e)); - } catch (final Exception e) { - log.warn("FinalizeAuthenticationTask has an internal error", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/StatusMessageProvider.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/StatusMessageProvider.java index d38da6fe..073f7513 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/StatusMessageProvider.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/provider/StatusMessageProvider.java @@ -94,8 +94,8 @@ public class StatusMessageProvider implements IStatusMessenger { public String getResponseErrorCode(Throwable throwable) { String errorCode = IStatusMessenger.CODES_EXTERNAL_ERROR_GENERIC; if (throwable instanceof EaafException) { - errorCode = ((EaafException) throwable).getErrorId(); - + errorCode = mapInternalErrorToExternalError(((EaafException) throwable).getErrorId()); + } // TODO: maybe more internal switches are required diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java index 557e245a..1ea5a280 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java @@ -30,18 +30,47 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.utils.Random; -public class EidasCacheTransactionStoreDecorator implements ITransactionStorage { +public class EidasCacheTransactionStoreDecorator implements ITransactionStorage, HealthIndicator { private static final Logger log = LoggerFactory.getLogger(EidasCacheTransactionStoreDecorator.class); @Autowired(required = true) private CacheWithEidasBackend storage; @Override + public Health health() { + try { + final String key = Random.nextHexRandom16(); + final String value = Random.nextHexRandom16(); + + this.put(key, value, -1); + final String result = this.get(key, String.class); + this.remove(key); + + if (result != null && result.equals(value)) { + return Health.up().build(); + + } else { + log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); + return Health.down().build(); + + } + + } catch (final EaafException e) { + log.warn("Montioring: Can not read/write to storage.", e); + return Health.down().down(e).build(); + + } + } + + @Override public void changeKey(String oldKey, String newKey, Object value) throws EaafException { if (containsKey(oldKey)) { final TransactionStoreElement el = storage.get(oldKey); @@ -148,5 +177,4 @@ public class EidasCacheTransactionStoreDecorator implements ITransactionStorage } } - } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java index 26d442cb..3bda2932 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/SimpleInMemoryTransactionStorage.java @@ -33,13 +33,11 @@ import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; 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; -@Service("SimpleInMemoryTransactionStorage") public class SimpleInMemoryTransactionStorage implements ITransactionStorage { private static final Logger log = LoggerFactory.getLogger(SimpleInMemoryTransactionStorage.class); diff --git a/connector/src/main/resources/application.properties b/connector/src/main/resources/application.properties new file mode 100644 index 00000000..b13b6c18 --- /dev/null +++ b/connector/src/main/resources/application.properties @@ -0,0 +1,148 @@ +## Set Spring-Boot profile-configuration to 2.3 style +spring.config.use-legacy-processing=true + +## ApplicationServer configuration +server.servlet.contextPath=/ms_connector +#server.port=7080 + +app.build.artifactId=ms_connector + + +############################################################################# +## SpringBoot Admin client +spring.boot.admin.client.enabled=false + + + + +############################################################################# +## MS-speccific eIDAS-Connector configuration +#proxy.context.url.prefix= +eidas.ms.context.url.request.validation=false +#proxy.configRootDir=file:/.../config/ +eidas.ms.context.use.clustermode=true +eidas.ms.core.logging.level.info.errorcodes=auth.21 + +##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/high + +#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 +eidas.ms.auth.eIDAS.szrclient.eidasbind.mds.inject=false + + +# 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.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=false +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false + +##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=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.pvp2.metadata.url= +#eidas.ms.sp.0.policy.allowed.requested.targets=.* +#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false + + +##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/connector/src/main/resources/applicationContext.xml b/connector/src/main/resources/applicationContext.xml index 76682a2e..15ce0a55 100644 --- a/connector/src/main/resources/applicationContext.xml +++ b/connector/src/main/resources/applicationContext.xml @@ -14,10 +14,14 @@ http://www.springframework.org/schema/tx/spring-tx.xsd"> <context:annotation-config /> - <mvc:annotation-driven /> + <context:component-scan base-package="at.gv.egiz.eaaf.utils.springboot.ajp"/> +<!-- + <context:annotation-config /> + <mvc:annotation-driven /> <mvc:default-servlet-handler /> - +--> + <mvc:interceptors> <bean class="at.asitplus.eidas.specific.connector.interceptor.WebFrontEndSecurityInterceptor" /> @@ -27,13 +31,24 @@ </bean> </mvc:interceptors> + <bean id="springContextClosingHandler" + class="at.asitplus.eidas.specific.connector.SpringContextCloseHandler" /> + +<!-- <context:property-placeholder location="${eidas.ms.configuration}" /> + --> + <beans profile="deprecatedConfig"> <bean id="BasicMSSpecificNodeConfig" class="at.asitplus.eidas.specific.connector.config.BasicConfigurationProvider"> - <constructor-arg - value="#{systemProperties['eidas.ms.configuration']}" /> + <constructor-arg value="#{systemProperties['eidas.ms.configuration']}" /> </bean> + </beans> + <beans profile="!deprecatedConfig"> + <bean id="springBootMsSpecificNodeConfig" + class="at.asitplus.eidas.specific.connector.config.SpringBootBasicConfigurationProvider" /> + + </beans> </beans> diff --git a/connector/src/main/resources/log4j.properties b/connector/src/main/resources/log4j.properties deleted file mode 100644 index 81e54aae..00000000 --- a/connector/src/main/resources/log4j.properties +++ /dev/null @@ -1,55 +0,0 @@ -# commons-logging setup -org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory - -# define log4j root loggers -log4j.rootLogger=info,stdout, console - -log4j.logger.at.gv.egiz.eaaf=info, msnode -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/connector/src/main/resources/logback.xml b/connector/src/main/resources/logback.xml index a0a9995e..7aa2d0cc 100644 --- a/connector/src/main/resources/logback.xml +++ b/connector/src/main/resources/logback.xml @@ -11,14 +11,14 @@ <appender name="msnode" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender --> - <File>${catalina.base}/logs/eidas-ms-reversion.log</File> + <File>logs/eidas-ms-specific.log</File> <encoder> <pattern>%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <maxIndex>9999</maxIndex> - <FileNamePattern>${catalina.base}/logs/eidas-ms-reversion.log.%i + <FileNamePattern>logs/eidas-ms-specific.log.%i </FileNamePattern> </rollingPolicy> <triggeringPolicy @@ -29,14 +29,14 @@ <appender name="EIDASNODE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender --> - <File>${catalina.base}/logs/eIDAS_node.log</File> + <File>logs/eIDAS_node.log</File> <encoder> <pattern>%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <maxIndex>9999</maxIndex> - <FileNamePattern>${catalina.base}/logs/eIDAS_node.log.%i + <FileNamePattern>logs/eIDAS_node.log.%i </FileNamePattern> </rollingPolicy> <triggeringPolicy @@ -47,14 +47,14 @@ <appender name="reversion" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender --> - <File>${catalina.base}/logs/eidas-ms-reversion.log</File> + <File>logs/eidas-ms-reversion.log</File> <encoder> <pattern>%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <maxIndex>9999</maxIndex> - <FileNamePattern>${catalina.base}/logs/eidas-ms-reversion.log.%i + <FileNamePattern>logs/eidas-ms-reversion.log.%i </FileNamePattern> </rollingPolicy> <triggeringPolicy @@ -65,14 +65,14 @@ <appender name="statistic" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender --> - <File>${catalina.base}/logs/eidas-ms-statistic.log</File> + <File>logs/eidas-ms-statistic.log</File> <encoder> <pattern>%m%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <maxIndex>9999</maxIndex> - <FileNamePattern>${catalina.base}/logs/eidas-ms-statistic.log.%i + <FileNamePattern>logs/eidas-ms-statistic.log.%i </FileNamePattern> </rollingPolicy> <triggeringPolicy @@ -83,14 +83,14 @@ <appender name="stdout" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!--See also http://logback.qos.ch/manual/appenders.html#RollingFileAppender --> - <File>${catalina.base}/logs/console.log</File> + <File>logs/console.log</File> <encoder> <pattern>%5p | %d{dd HH:mm:ss,SSS} | %t | %m%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <maxIndex>9999</maxIndex> - <FileNamePattern>${catalina.base}/logs/console.log.%i + <FileNamePattern>logs/console.log.%i </FileNamePattern> </rollingPolicy> <triggeringPolicy diff --git a/connector/src/main/resources/specific_eIDAS_connector.beans.xml b/connector/src/main/resources/specific_eIDAS_connector.beans.xml index 5cf0d5b8..f6fdeefe 100644 --- a/connector/src/main/resources/specific_eIDAS_connector.beans.xml +++ b/connector/src/main/resources/specific_eIDAS_connector.beans.xml @@ -11,23 +11,24 @@ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> - <context:annotation-config /> - <mvc:annotation-driven /> - <mvc:default-servlet-handler /> + <import resource="common_gui.beans.xml"/> <bean id="WebResourceConfiguration" class="at.asitplus.eidas.specific.connector.config.StaticResourceConfiguration" /> - <bean id="ProcessEngineSignalController" + <bean id="processEngineSignalController" class="at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController" /> - <bean id="MonitoringController" - class="at.asitplus.eidas.specific.connector.controller.MonitoringController"> + <bean id="saml2MetadataGeneration" + class="at.asitplus.eidas.specific.connector.health.Saml2MetadataHealthIndicator"> <property name="pvpIdpCredentials"> <ref bean="PVPEndPointCredentialProvider" /> </property> </bean> + <bean id="eidasNodeMetadata" + class="at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator" /> + <bean id="AuthenticationManager" class="at.asitplus.eidas.specific.connector.auth.AuthenticationManager" /> @@ -43,7 +44,7 @@ <bean id="PVPMetadataConfigurationFactory" class="at.asitplus.eidas.specific.connector.provider.PvpMetadataConfigurationFactory" /> - <bean id="PVP2XProtocol" + <bean id="pvp2SProfileEndpoint" class="at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint"> <property name="pvpIdpCredentials"> <ref bean="PVPEndPointCredentialProvider" /> @@ -96,17 +97,6 @@ <bean id="mvcGUIBuilderImpl" class="at.asitplus.eidas.specific.connector.gui.SpringMvcGuiFormBuilderImpl" /> - <bean id="templateEngine" - class="org.thymeleaf.spring5.SpringTemplateEngine"> - <property name="templateResolver" ref="templateResolver" /> - </bean> - - <bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> - <property name="order" value="2" /> - <property name="templateEngine" ref="templateEngine" /> - <property name="characterEncoding" value="UTF-8" /> - </bean> - <bean id="StatusMessageProvider" class="at.asitplus.eidas.specific.connector.provider.StatusMessageProvider" /> diff --git a/connector/src/main/resources/specific_eIDAS_connector.storage.beans.xml b/connector/src/main/resources/specific_eIDAS_connector.storage.beans.xml index 08c7b672..2e4d1742 100644 --- a/connector/src/main/resources/specific_eIDAS_connector.storage.beans.xml +++ b/connector/src/main/resources/specific_eIDAS_connector.storage.beans.xml @@ -27,12 +27,15 @@ <bean id="msNodeCacheImpl" class="eu.eidas.auth.cache.ConcurrentCacheServiceIgniteSpecificCommunicationImpl"> - <property - name="igniteInstanceInitializerSpecificCommunication" - ref="eidasIgniteInstanceInitializerSpecificCommunication" /> + <property name="igniteInstanceInitializerSpecificCommunication" ref="eidasIgniteInstanceInitializerSpecificCommunication" /> <property name="cacheName" value="msConnectorCache" /> </bean> + <bean id="IgniteClusterState" + class="at.asitplus.eidas.specific.connector.health.IgniteClusterHealthIndicator"> + <property name="igniteInstanceInitializerSpecificCommunication" ref="eidasIgniteInstanceInitializerSpecificCommunication" /> + </bean> + <!-- bean id="defaultHazelcastInstance" class="java.lang.String"> <constructor-arg value="eidasHazelcastInstance"/> </bean> <bean id="eidasHazelcastInstanceInitializer" diff --git a/connector/src/main/resources/tomcat.properties b/connector/src/main/resources/tomcat.properties new file mode 100644 index 00000000..38ab5a64 --- /dev/null +++ b/connector/src/main/resources/tomcat.properties @@ -0,0 +1,15 @@ +tomcat.ajp.enabled=true +#tomcat.ajp.port=41009 +#tomcat.ajp.additionalAttributes.secretrequired=true +#tomcat.ajp.additionalAttributes.secret= + +server.tomcat.accesslog.buffered=false +server.tomcat.accesslog.prefix=tomcat-access_log +server.tomcat.accesslog.directory=logs/ +server.tomcat.accesslog.enabled=true +server.tomcat.accesslog.file-date-format=.yyyy-MM-dd +server.tomcat.accesslog.pattern=common +server.tomcat.accesslog.rename-on-rotate=false +server.tomcat.accesslog.request-attributes-enabled=true +server.tomcat.accesslog.rotate=true +server.tomcat.accesslog.suffix=.log
\ No newline at end of file diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java deleted file mode 100644 index 1721fe61..00000000 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthenticationDataBuilderTest.java +++ /dev/null @@ -1,107 +0,0 @@ -package at.asitplus.eidas.specific.connector.test; - - -import at.asitplus.eidas.specific.connector.builder.AuthenticationDataBuilder; -import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; -import at.gv.egiz.eaaf.core.api.data.EaafConfigConstants; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.api.idp.IConfiguration; -import at.gv.egiz.eaaf.core.exceptions.EaafAuthenticationException; -import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; -import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; -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; -import org.apache.commons.lang3.RandomStringUtils; -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.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 java.util.HashMap; -import java.util.Map; - -import static at.asitplus.eidas.specific.connector.MsEidasNodeConstants.PROP_CONFIG_SP_NEW_EID_MODE; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration({"/applicationContext.xml", "/SpringTest_connector.beans.xml", "/eaaf_core.beans.xml", "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml"}) -@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<String, String> 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.setSpConfig(oaParam); - pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); - authBlock = RandomStringUtils.randomAlphanumeric(20); - eidasBind = RandomStringUtils.randomAlphanumeric(20); - pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(Constants.SZR_AUTHBLOCK, authBlock); - pendingReq.getSessionData(AuthProcessDataWrapper.class).setGenericDataToSession(Constants.EIDAS_BIND, eidasBind); - LocaleContextHolder.resetLocaleContext(); - } - - @Test - public void first() throws EaafAuthenticationException { - IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); - - Assert.assertNotNull("AuthData null", authData); - Assert.assertNotNull("authBlock null", authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class)); - Assert.assertNotNull("eidasBind null", authData.getGenericData(Constants.EIDAS_BIND, String.class)); - Assert.assertNotNull("eidasBind null", authData.getEidasQaaLevel()); - String authBlock = authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class); - String eidasBind = authData.getGenericData(Constants.EIDAS_BIND, String.class); - - Assert.assertEquals("authBlock not equal", authBlock, this.authBlock); - Assert.assertEquals("eidasBind not equal", eidasBind, this.eidasBind); - } - -} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java new file mode 100644 index 00000000..77037415 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/FullStartUpAndProcessTest.java @@ -0,0 +1,485 @@ +package at.asitplus.eidas.specific.connector.test; + +import static org.mockito.ArgumentMatchers.any; +import static org.powermock.api.mockito.PowerMockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.util.Map; +import java.util.Timer; + +import javax.xml.transform.TransformerException; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.ignite.Ignition; +import org.joda.time.DateTime; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.opensaml.core.config.InitializationException; +import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.core.StatusResponseType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.core.io.ResourceLoader; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.util.Base64Utils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.skjolberg.mockito.soap.SoapServiceRule; + +import at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController; +import at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint; +import at.asitplus.eidas.specific.connector.provider.PvpEndPointCredentialProvider; +import at.asitplus.eidas.specific.connector.provider.PvpMetadataProvider; +import at.asitplus.eidas.specific.connector.test.saml2.Pvp2SProfileEndPointTest; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.EidasSignalServlet; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.service.EidasAttributeRegistry; +import at.gv.egiz.components.spring.api.SpringBootApplicationContextInitializer; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.idp.controller.ProtocolFinalizationController; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.exception.CredentialsNotAvailableException; +import at.gv.egiz.eaaf.modules.pvp2.exception.SamlSigningException; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import at.gv.egiz.eaaf.modules.pvp2.sp.impl.utils.AssertionAttributeExtractor; +import eu.eidas.auth.commons.attribute.AttributeDefinition; +import eu.eidas.auth.commons.attribute.ImmutableAttributeMap; +import eu.eidas.auth.commons.light.ILightRequest; +import eu.eidas.auth.commons.protocol.impl.AuthenticationResponse; +import eu.eidas.auth.commons.tx.BinaryLightToken; +import eu.eidas.specificcommunication.SpecificCommunicationDefinitionBeanNames; +import eu.eidas.specificcommunication.exception.SpecificCommunicationException; +import eu.eidas.specificcommunication.protocol.SpecificCommunicationService; +import lombok.val; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.XMLParserException; +import szrservices.SZR; +import szrservices.SignContentEntry; +import szrservices.SignContentResponseType; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest +@ContextConfiguration(initializers = { + org.springframework.boot.context.config.DelegatingApplicationContextInitializer.class, + SpringBootApplicationContextInitializer.class + }) +@TestPropertySource(locations = { "file:src/test/resources/config/junit_config_1_springboot.properties" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +@ActiveProfiles(profiles = {"JUNIT", "jUnitTestMode"}) +public class FullStartUpAndProcessTest { + + private static final String FINAL_REDIRECT = "http://localhost/finalizeAuthProtocol?pendingid="; + + @Autowired private WebApplicationContext wac; + @Autowired private PvpEndPointCredentialProvider credentialProvider; + @Autowired private PvpMetadataProvider metadataProvider; + @Autowired private ResourceLoader resourceLoader; + @Autowired private EidasAttributeRegistry attrRegistry; + + @Autowired private Pvp2SProfileEndpoint sProfile; + @Autowired private ProcessEngineSignalController signal; + @Autowired private EidasSignalServlet eidasSignal; + @Autowired private ProtocolFinalizationController finalize; + + @Rule + public final SoapServiceRule soap = SoapServiceRule.newInstance(); + + private SZR szrMock; + + private String cc; + private String givenName; + private String familyName; + private String dateOfBirth; + private String personalId; + private String vsz; + private String eidasBind; + + + /** + * jUnit class initializer. + * @throws InterruptedException In case of an error + * @throws ComponentInitializationException In case of an error + * @throws InitializationException In case of an error + * + */ + @BeforeClass + public static void classInitializer() throws InterruptedException, InitializationException, ComponentInitializationException { + final String current = new java.io.File(".").toURI().toString(); + System.clearProperty("eidas.ms.configuration"); + + //eIDAS Ref. Impl. properties + System.setProperty("EIDAS_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_CONNECTOR_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_PROXY_SERVICE_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + + EaafOpenSaml3xInitializer.eaafInitialize(); + + } + + /** + * Test shut-down. + * + * @throws IOException In case of an error + */ + @AfterClass + public static void closeIgniteNode() throws IOException { + System.out.println("Closiong Ignite Node ... "); + Ignition.stopAll(true); + + } + + /** + * jUnit test set-up. + * + * + */ + @Before + public void setup() throws IOException { + DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(this.wac); + @SuppressWarnings("rawtypes") + Map<String, FilterRegistrationBean> filters = wac.getBeansOfType(FilterRegistrationBean.class); + for (FilterRegistrationBean<?> filter : filters.values()) { + if (filter.isEnabled()) { + builder.addFilter(filter.getFilter(), "/*"); + + } + } + + szrMock = soap.mock(SZR.class, "http://localhost:1234/demoszr"); + + + + cc = RandomStringUtils.randomAlphabetic(2).toUpperCase(); + personalId = cc + "/AT/" + RandomStringUtils.randomNumeric(64); + familyName = RandomStringUtils.randomAlphabetic(10); + givenName = RandomStringUtils.randomAlphabetic(10); + dateOfBirth = "2015-10-12"; + + vsz = RandomStringUtils.randomNumeric(10); + eidasBind = RandomStringUtils.randomAlphanumeric(50); + + } + + @Test + public void userStopProcess() throws UnsupportedEncodingException, XMLParserException, UnmarshallingException, + TransformerException, IOException, MarshallingException, ComponentInitializationException, EaafException { + //start authentication process by sending a SAML2 Authn-Request + MockHttpServletRequest saml2Req = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + injectSaml2AuthnReq(saml2Req); + MockHttpServletResponse selectCountryResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(saml2Req, selectCountryResp)); + + // send SAML2 AuthnRequest + sProfile.pvpIdpPostRequest(saml2Req, selectCountryResp); + + //check country-selection response + Assert.assertEquals("no country-selection page", 200, selectCountryResp.getStatus()); + Assert.assertEquals("cc-selection page", "text/html;charset=UTF-8", selectCountryResp.getContentType()); + String selectionPage = selectCountryResp.getContentAsString(); + Assert.assertNotNull("selectionPage is null", selectionPage); + Assert.assertFalse("selectionPage is empty", selectionPage.isEmpty()); + + String pendingReqId = extractRequestToken(selectionPage, + "<input type=\"hidden\" name=\"pendingid\" value=\""); + Assert.assertFalse("PendingReqId", pendingReqId.isEmpty()); + + + // set-up user-stop request + MockHttpServletRequest userStopReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + userStopReq.setParameter("pendingid", pendingReqId); + userStopReq.setParameter(EaafConstants.PARAM_HTTP_STOP_PROCESS, "true"); + + MockHttpServletResponse finalizeResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(userStopReq, finalizeResp)); + + // send user-stop request + signal.performGenericAuthenticationProcess(userStopReq, finalizeResp); + + //validate state + Assert.assertEquals("forward to finalization", 302, finalizeResp.getStatus()); + Assert.assertNotNull("missing redirect header", finalizeResp.getHeader("Location")); + Assert.assertTrue("wrong redirect header", finalizeResp.getHeader("Location").startsWith(FINAL_REDIRECT)); + String finalPendingReqId = finalizeResp.getHeader("Location").substring(FINAL_REDIRECT.length()); + Assert.assertFalse("final pendingRequestId", finalPendingReqId.isEmpty()); + + //set-up finalization request + MockHttpServletRequest finalizationReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + finalizationReq.setParameter("pendingid", finalPendingReqId); + + MockHttpServletResponse saml2Resp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(finalizationReq, saml2Resp)); + + // exexcute finalization step + finalize.finalizeAuthProtocol(finalizationReq, saml2Resp); + + //validate state + Assert.assertEquals("forward to finalization", 200, saml2Resp.getStatus()); + Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", saml2Resp.getContentType()); + String saml2RespPage = saml2Resp.getContentAsString(); + Assert.assertNotNull("selectionPage is null", saml2RespPage); + Assert.assertFalse("selectionPage is empty", saml2RespPage.isEmpty()); + + //validate SAML2 response + String saml2RespB64 = extractRequestToken(saml2RespPage, + "<input type=\"hidden\" name=\"SAMLResponse\" value=\""); + Assert.assertNotNull("SAML2 response", saml2RespB64); + + StatusResponseType saml2 = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(Base64Utils.decodeFromString(saml2RespB64))); + Assert.assertEquals("SAML2 status", "urn:oasis:names:tc:SAML:2.0:status:Responder", + saml2.getStatus().getStatusCode().getValue()); + Assert.assertEquals("ms-connector status", "1005", + saml2.getStatus().getStatusCode().getStatusCode().getValue()); + + } + + @Test + public void fullSuccessProcess() throws EaafException, Exception { + //start authentication process by sending a SAML2 Authn-Request + MockHttpServletRequest saml2Req = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + injectSaml2AuthnReq(saml2Req); + MockHttpServletResponse selectCountryResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(saml2Req, selectCountryResp)); + + // send SAML2 AuthnRequest + sProfile.pvpIdpPostRequest(saml2Req, selectCountryResp); + + //check country-selection response + Assert.assertEquals("no country-selection page", 200, selectCountryResp.getStatus()); + Assert.assertEquals("cc-selection page", "text/html;charset=UTF-8", selectCountryResp.getContentType()); + String selectionPage = selectCountryResp.getContentAsString(); + Assert.assertNotNull("selectionPage is null", selectionPage); + Assert.assertFalse("selectionPage is empty", selectionPage.isEmpty()); + + String pendingReqId = extractRequestToken(selectionPage, + "<input type=\"hidden\" name=\"pendingid\" value=\""); + Assert.assertFalse("PendingReqId", pendingReqId.isEmpty()); + + + // set-up country-selection request + MockHttpServletRequest selectCountryReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + selectCountryReq.setParameter("pendingid", pendingReqId); + selectCountryReq.setParameter("selectedCountry", cc); + + MockHttpServletResponse forwardEidasNodeResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(selectCountryReq, forwardEidasNodeResp)); + + // send country-selection request + signal.performGenericAuthenticationProcess(selectCountryReq, forwardEidasNodeResp); + + //check forward to eIDAS node response + Assert.assertEquals("forward to eIDAS Node", 200, forwardEidasNodeResp.getStatus()); + Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", forwardEidasNodeResp.getContentType()); + String forwardPage = forwardEidasNodeResp.getContentAsString(); + Assert.assertNotNull("forward to eIDAS Node is null", forwardPage); + Assert.assertFalse("forward to eIDAS Node is empty", forwardPage.isEmpty()); + + String eidasNodeReqToken = extractRequestToken(forwardPage, + "<input type=\"hidden\" name=\"token\" value=\""); + Assert.assertFalse("eidas req. token", eidasNodeReqToken.isEmpty()); + + //check eIDAS node request and build respose + String eidasRespToken = validateEidasNodeRequestAndBuildResponse(eidasNodeReqToken); + Assert.assertFalse("eidas resp. token", eidasRespToken.isEmpty()); + + + // set-up eIDAS-node response + MockHttpServletRequest eidasNodeRespReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + eidasNodeRespReq.setParameter("token", eidasRespToken); + + MockHttpServletResponse finalizeResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(eidasNodeRespReq, finalizeResp)); + + injectSzrResponse(); + + //excute eIDAS node response + eidasSignal.restoreEidasAuthProcess(eidasNodeRespReq, finalizeResp); + + //validate state + Assert.assertEquals("forward to finalization", 302, finalizeResp.getStatus()); + Assert.assertNotNull("missing redirect header", finalizeResp.getHeader("Location")); + Assert.assertTrue("wrong redirect header", finalizeResp.getHeader("Location").startsWith(FINAL_REDIRECT)); + String finalPendingReqId = finalizeResp.getHeader("Location").substring(FINAL_REDIRECT.length()); + Assert.assertFalse("final pendingRequestId", finalPendingReqId.isEmpty()); + + + //set-up finalization request + MockHttpServletRequest finalizationReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + finalizationReq.setParameter("pendingid", finalPendingReqId); + + MockHttpServletResponse saml2Resp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(finalizationReq, saml2Resp)); + + // exexcute finalization step + finalize.finalizeAuthProtocol(finalizationReq, saml2Resp); + + //validate state + Assert.assertEquals("forward to finalization", 200, saml2Resp.getStatus()); + Assert.assertEquals("forward to eIDAS Node page", "text/html;charset=UTF-8", saml2Resp.getContentType()); + String saml2RespPage = saml2Resp.getContentAsString(); + Assert.assertNotNull("selectionPage is null", saml2RespPage); + Assert.assertFalse("selectionPage is empty", saml2RespPage.isEmpty()); + + //validate SAML2 response + String saml2RespB64 = extractRequestToken(saml2RespPage, + "<input type=\"hidden\" name=\"SAMLResponse\" value=\""); + Assert.assertNotNull("SAML2 response", saml2RespB64); + + StatusResponseType saml2 = (StatusResponseType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(Base64Utils.decodeFromString(saml2RespB64))); + Assert.assertEquals("SAML2 status", Constants.SUCCESS_URI, saml2.getStatus().getStatusCode().getValue()); + + final AssertionAttributeExtractor extractor = new AssertionAttributeExtractor(saml2); + Assert.assertEquals("wrong resp attr. size", 6, extractor.getAllIncludeAttributeNames().size()); + Assert.assertEquals("Wrong attr: LoA ", "http://eidas.europa.eu/LoA/high", + extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.108")); + Assert.assertEquals("Wrong attr: PVP_VERSION ", "2.2", + extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.10")); + Assert.assertEquals("Wrong attr: EID_ISSUER_NATION ", cc, + extractor.getSingleAttributeValue("urn:oid:1.2.40.0.10.2.1.1.261.32")); + Assert.assertEquals("Wrong attr: eidasBind", eidasBind, + extractor.getSingleAttributeValue("urn:eidgvat:attributes.eidbind")); + Assert.assertNotNull("Wrong attr: authBlock", + extractor.getSingleAttributeValue("urn:eidgvat:attributes.authblock.signed")); + Assert.assertNotNull("Wrong attr: piiTras.Id ", + extractor.getSingleAttributeValue("urn:eidgvat:attributes.piiTransactionId")); + + } + + private void injectSzrResponse() throws Exception { + + when(szrMock, "getStammzahlEncrypted", any(), any()).thenReturn(vsz); + val signContentResp = new SignContentResponseType(); + final SignContentEntry signContentEntry = new SignContentEntry(); + signContentEntry.setValue(eidasBind); + signContentResp.getOut().add(signContentEntry); + when(szrMock, "signContent", any(), any(), any()).thenReturn(signContentResp); + + } + + private String validateEidasNodeRequestAndBuildResponse(String eidasNodeReqToken) + throws SpecificCommunicationException, URISyntaxException { + final SpecificCommunicationService springManagedSpecificConnectorCommunicationService = + (SpecificCommunicationService) wac.getBean( + SpecificCommunicationDefinitionBeanNames.SPECIFIC_CONNECTOR_COMMUNICATION_SERVICE.toString()); + + //read request and validate basic properties + ILightRequest req = springManagedSpecificConnectorCommunicationService.getAndRemoveRequest(eidasNodeReqToken, + attrRegistry.getCoreAttributeRegistry().getAttributes()); + + Assert.assertNotNull("eIDAS Node req", req); + Assert.assertEquals("Wrong CC", cc, req.getCitizenCountryCode()); + Assert.assertEquals("Wrong CC", EaafConstants.EIDAS_LOA_HIGH, req.getLevelOfAssurance()); + + + //set response from eIDAS node + BinaryLightToken respoToken = springManagedSpecificConnectorCommunicationService.putResponse( + buildDummyAuthResponse(Constants.SUCCESS_URI, req.getId())); + return Base64Utils.encodeToString(respoToken.getTokenBytes()); + + } + + private AuthenticationResponse buildDummyAuthResponse(String statusCode, String reqId) throws URISyntaxException { + final AttributeDefinition<?> attributeDef = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_PERSONALIDENTIFIER).first(); + final AttributeDefinition<?> attributeDef2 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_CURRENTFAMILYNAME).first(); + final AttributeDefinition<?> attributeDef3 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_CURRENTGIVENNAME).first(); + final AttributeDefinition<?> attributeDef4 = attrRegistry.getCoreAttributeRegistry().getByFriendlyName( + Constants.eIDAS_ATTR_DATEOFBIRTH).first(); + + final ImmutableAttributeMap attributeMap = ImmutableAttributeMap.builder() + .put(attributeDef, personalId) + .put(attributeDef2, familyName) + .put(attributeDef3, givenName) + .put(attributeDef4, dateOfBirth).build(); + + val b = new AuthenticationResponse.Builder(); + return b.id("_".concat(Random.nextHexRandom16())) + .issuer(RandomStringUtils.randomAlphabetic(10)) + .subject(RandomStringUtils.randomAlphabetic(10)) + .statusCode(statusCode) + .inResponseTo(reqId) + .subjectNameIdFormat("afaf") + .levelOfAssurance(EaafConstants.EIDAS_LOA_HIGH) + .attributes(attributeMap) + .build(); + + } + + private String extractRequestToken(String selectionPage, String selector) { + int start = selectionPage.indexOf(selector); + Assert.assertTrue("find no pendingReqId location start", start > 0); + int end = selectionPage.indexOf("\"", start + selector.length()); + Assert.assertTrue("find no pendingReqId location end", end > 0); + return selectionPage.substring(start + selector.length(), end); + + } + + private void injectSaml2AuthnReq(MockHttpServletRequest saml2Req) throws XMLParserException, UnmarshallingException, + SamlSigningException, CredentialsNotAvailableException, UnsupportedEncodingException, TransformerException, + IOException, MarshallingException, ComponentInitializationException { + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + RequestAbstractType signedAuthnReq = + Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true); + String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( + XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8")); + saml2Req.setParameter("SAMLRequest", b64); + + final org.springframework.core.io.Resource resource = resourceLoader.getResource( + "classpath:/data/metadata_valid_without_encryption.xml"); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); + + } +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java new file mode 100644 index 00000000..86df55df --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassExecutableModeTest.java @@ -0,0 +1,113 @@ +package at.asitplus.eidas.specific.connector.test; + +import java.io.IOException; +import java.lang.reflect.Field; + +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.ignite.Ignition; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.asitplus.eidas.specific.connector.SpringBootApplicationInitializer; +import at.gv.egiz.eaaf.core.impl.logging.DummyStatusMessager; +import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RunWith(BlockJUnit4ClassRunner.class) +public class MainClassExecutableModeTest { + + /** + * jUnit class initializer. + * @throws InterruptedException In case of an error + * + */ + @BeforeClass + public static void classInitializer() throws InterruptedException { + final String current = new java.io.File(".").toURI().toString(); + System.clearProperty("eidas.ms.configuration"); + + //eIDAS Ref. Impl. properties + System.setProperty("EIDAS_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_CONNECTOR_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_PROXY_SERVICE_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + + } + + /** + * Initializer. + * @throws InterruptedException In case of an error + * + */ + @AfterClass + public static void closeIgniteNode() throws InterruptedException { + System.out.println("Closing Ignite Node ... "); + + log.info("Stopping already running Apache Ignite nodes ... "); + Ignition.stopAll(true); + Thread.sleep(1000); + + } + + /** + * Test reseter. + * + */ + @After + public void cleanJvmState() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + final Field field = LogMessageProviderFactory.class.getDeclaredField("internalMessager"); + field.setAccessible(true); + field.set(null, new DummyStatusMessager()); + + System.clearProperty("eidas.ms.configuration"); + SpringBootApplicationInitializer.exit(); + + } + + + @Test + public void validConfigLocation() throws Throwable { + SpringBootApplicationInitializer + .main(new String[] { + "--spring.config.location=src/test/resources/config/junit_config_2_springboot.properties,classpath:/application.properties", + "--spring.profiles.active=jUnitTestMode" }); + + System.out.println("Is started!"); + + // test Spring-Actuator http Basic-Auth + testSpringActuatorSecurity(); + + } + + private void testSpringActuatorSecurity() throws ClientProtocolException, IOException { + // check if authentication works on actuator end-point + final HttpClientBuilder builder = HttpClients.custom(); + final CloseableHttpClient client = builder.build(); + Assert.assertNotNull("httpClient", client); + + final HttpUriRequest httpGetInfo = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); + final CloseableHttpResponse httpRespInfo = client.execute(httpGetInfo); + Assert.assertEquals("http statusCode", 200, httpRespInfo.getStatusLine().getStatusCode()); + + final HttpUriRequest httpGetHealth = new HttpGet("http://localhost:8080/ms_connector/actuator/health"); + final CloseableHttpResponse httpRespHealth = client.execute(httpGetHealth); + Assert.assertEquals("http statusCode", 503, httpRespHealth.getStatusLine().getStatusCode()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java new file mode 100644 index 00000000..07ef4968 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/MainClassWebAppModeTest.java @@ -0,0 +1,134 @@ +package at.asitplus.eidas.specific.connector.test; + +import java.io.IOException; +import java.lang.reflect.Field; + +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.ignite.Ignition; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +import at.asitplus.eidas.specific.connector.SpringBootApplicationInitializer; +import at.gv.egiz.eaaf.core.impl.logging.DummyStatusMessager; +import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; + +@RunWith(BlockJUnit4ClassRunner.class) +public class MainClassWebAppModeTest { + + /** + * jUnit class initializer. + * + */ + @BeforeClass + public static void classInitializer() { + final String current = new java.io.File(".").toURI().toString(); + + //eIDAS Ref. Impl. properties + System.setProperty("EIDAS_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_CONNECTOR_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + System.setProperty("SPECIFIC_PROXY_SERVICE_CONFIG_REPOSITORY", current.substring("file:".length()) + + "../basicConfig/eIDAS/"); + + } + + /** + * Initializer. + * + */ + @AfterClass + public static void closeIgniteNode() { + System.out.println("Closing Ignite Node ... "); + Ignition.stopAll(true); + + } + + /** + * Test reseter. + * + */ + @After + public void cleanJvmState() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + final Field field = LogMessageProviderFactory.class.getDeclaredField("internalMessager"); + field.setAccessible(true); + field.set(null, new DummyStatusMessager()); + + System.clearProperty("eidas.ms.configuration"); + SpringBootApplicationInitializer.exit(); + + } + + @Test + public void wrongConfigLocation() throws Throwable { + //MS-specific connector property + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + + "src/test/resources/config/notextist.properties"); + + try { + //starting application + SpringBootApplicationInitializer + .main(new String[] { + "--spring.profiles.active=jUnitTestMode" }); + Assert.fail("Missing configuration not detected"); + + } catch (final Exception e) { + Assert.assertNotNull("Exception is null", e); + + } + } + + + @Test + public void systemdConfigLocation() throws Throwable { + //MS-specific connector property + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + + "src/test/resources/config/junit_config_1_springboot.properties"); + + //starting application + SpringBootApplicationInitializer + .main(new String[] { + "--spring.profiles.active=jUnitTestMode,springBoot" }); + + System.out.println("Is started!"); + + // test Spring-Actuator http Basic-Auth + testSpringActuatorSecurity(); + + + + + } + + private void testSpringActuatorSecurity() throws ClientProtocolException, IOException { + // check if authentication works on actuator end-point + final HttpClientBuilder builder = HttpClients.custom(); + final CloseableHttpClient client = builder.build(); + Assert.assertNotNull("httpClient", client); + + final HttpUriRequest httpGetInfo = new HttpGet("http://localhost:8080/ms_connector/actuator/info"); + final CloseableHttpResponse httpRespInfo = client.execute(httpGetInfo); + Assert.assertEquals("http statusCode", 200, httpRespInfo.getStatusLine().getStatusCode()); + + + final HttpUriRequest httpGetHealth = new HttpGet("http://localhost:8080/ms_connector/actuator/health"); + final CloseableHttpResponse httpRespHealth = client.execute(httpGetHealth); + Assert.assertEquals("http statusCode", 503, httpRespHealth.getStatusLine().getStatusCode()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java index b7c6cd44..5c0a1420 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/AuthBlockAttributeBuilderTest.java @@ -2,6 +2,8 @@ package at.asitplus.eidas.specific.connector.test.attributes; import static at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_NAME; +import java.util.Base64; + import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -13,6 +15,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import at.asitplus.eidas.specific.connector.attributes.AuthBlockAttributeBuilder; import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; import at.gv.egiz.eaaf.core.api.idp.IAuthData; import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; @@ -42,6 +45,19 @@ public class AuthBlockAttributeBuilderTest extends AbstractAttributeBuilderTest } @Test + public void checkName() { + Assert.assertEquals("Wrong attr. name", + ExtendedPvpAttributeDefinitions.EID_AUTHBLOCK_SIGNED_NAME, attrBuilde.getName()); + + } + + @Test + public void checkEmptyAttribute() { + Assert.assertNull("empty attr.", attrBuilde.buildEmpty(gen)); + + } + + @Test public void okTest() { log.info("starting: " + mTestName); try { @@ -50,7 +66,8 @@ public class AuthBlockAttributeBuilderTest extends AbstractAttributeBuilderTest final String value = attrBuilde.build(spConfig, authData, gen); - Assert.assertEquals("Authblock build wrong", JSW, value); + Assert.assertNotNull("AuthBlock", value); + Assert.assertEquals("Authblock build wrong", JSW, new String(Base64.getDecoder().decode(value))); } catch (final Exception e) { Assert.assertNull("Attr. builder has an exception", e); diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java index 254efb59..9a2c6cdc 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/attributes/EidasBindAttributeBuilderTest.java @@ -1,13 +1,7 @@ package at.asitplus.eidas.specific.connector.test.attributes; -import at.asitplus.eidas.specific.connector.attributes.EidasBindAttributeBuilder; -import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; -import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; -import at.gv.egiz.eaaf.core.api.idp.IAuthData; -import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; -import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; -import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest; -import lombok.extern.slf4j.Slf4j; +import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.EIDAS_BIND; + import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -17,7 +11,14 @@ import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import static at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants.EIDAS_BIND; +import at.asitplus.eidas.specific.connector.attributes.EidasBindAttributeBuilder; +import at.gv.egiz.eaaf.core.api.data.ExtendedPvpAttributeDefinitions; +import at.gv.egiz.eaaf.core.api.idp.IAttributeBuilder; +import at.gv.egiz.eaaf.core.api.idp.IAuthData; +import at.gv.egiz.eaaf.core.exceptions.UnavailableAttributeException; +import at.gv.egiz.eaaf.core.impl.idp.AuthenticationData; +import at.gv.egiz.eaaf.core.impl.idp.auth.attributes.AbstractAttributeBuilderTest; +import lombok.extern.slf4j.Slf4j; @Slf4j @@ -36,6 +37,19 @@ public class EidasBindAttributeBuilderTest extends AbstractAttributeBuilderTest } @Test + public void checkName() { + Assert.assertEquals("Wrong attr. name", + ExtendedPvpAttributeDefinitions.EID_EIDBIND_NAME, attrBuilde.getName()); + + } + + @Test + public void checkEmptyAttribute() { + Assert.assertNull("empty attr.", attrBuilde.buildEmpty(gen)); + + } + + @Test public void okTest() { log.info("starting: " + mTestName); try { diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/config/BasicConfigurationTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/config/BasicConfigurationTest.java new file mode 100644 index 00000000..80307ea2 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/config/BasicConfigurationTest.java @@ -0,0 +1,137 @@ +package at.asitplus.eidas.specific.connector.test.config; + +import java.net.MalformedURLException; +import java.net.URL; +import java.security.cert.CertificateException; + +import org.junit.Assert; +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.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +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 at.asitplus.eidas.specific.connector.config.ServiceProviderConfiguration; +import at.gv.egiz.eaaf.core.api.data.EaafConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; +import at.gv.egiz.eaaf.core.api.idp.ISpConfiguration; +import at.gv.egiz.eaaf.core.exceptions.EaafConfigurationException; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/applicationContext.xml", + "/specific_eIDAS_connector.beans.xml", + "/eaaf_core.beans.xml", + "/eaaf_pvp.beans.xml", + "/eaaf_pvp_idp.beans.xml", + "/spring/SpringTest-context_simple_storage.xml" }) +@WebAppConfiguration +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) +@ActiveProfiles(profiles = {"deprecatedConfig"}) +public class BasicConfigurationTest { + + @Autowired private IConfigurationWithSP basicConfig; + + /** + * jUnit class initializer. + * @throws ComponentInitializationException In case of an error + * @throws InitializationException In case of an error + * @throws CertificateException + * + */ + @BeforeClass + public static void classInitializer() throws InitializationException, + ComponentInitializationException, CertificateException { + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_1.properties"); + + } + + + @Test + public void basicConfig() throws MalformedURLException, EaafException { + Assert.assertEquals("validate req. URL", "http://localhost", + basicConfig.validateIdpUrl(new URL("http://junit/test"))); + + Assert.assertEquals("validate req. URL", "http://localhost", + basicConfig.validateIdpUrl(new URL("http://localhost/test1/test"))); + + } + + @Test + public void loadSpNotExist() throws EaafConfigurationException { + //check + ISpConfiguration sp = basicConfig.getServiceProviderConfiguration( + "https://not/exist"); + + //validate state + Assert.assertNull("spConfig", sp); + + + } + + @Test + public void loadSpDefault() throws EaafConfigurationException { + //check + ISpConfiguration sp = basicConfig.getServiceProviderConfiguration( + "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"); + + //validate state + Assert.assertNotNull("spConfig", sp); + Assert.assertEquals("BaseId transfare restrication", true, sp.hasBaseIdTransferRestriction()); + Assert.assertEquals("BaseId process restrication", false, sp.hasBaseIdInternalProcessingRestriction()); + + Assert.assertEquals("req. LoA size", 1, sp.getRequiredLoA().size()); + Assert.assertEquals("req. LoA", EaafConstants.EIDAS_LOA_HIGH, sp.getRequiredLoA().get(0)); + Assert.assertEquals("LoA matching mode", + EaafConstants.EIDAS_LOA_MATCHING_MINIMUM, sp.getLoAMatchingMode()); + + } + + @Test + public void loadSpNoBaseIdTransferRestriction() throws EaafException { + //check + ServiceProviderConfiguration sp = basicConfig.getServiceProviderConfiguration( + "https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata", ServiceProviderConfiguration.class); + + //validate state + Assert.assertNotNull("spConfig", sp); + Assert.assertNull("bPKTarget already set", sp.getAreaSpecificTargetIdentifier()); + + //validate baseId transfer restriction + sp.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_CDID + "ZP"); + Assert.assertEquals("BaseId restrication", false, sp.hasBaseIdTransferRestriction()); + Assert.assertEquals("bPKTarget", EaafConstants.URN_PREFIX_CDID + "ZP", sp.getAreaSpecificTargetIdentifier()); + + sp.setBpkTargetIdentifier(EaafConstants.URN_PREFIX_WBPK_TARGET_WITH_X + "FN+123456h"); + Assert.assertEquals("BaseId restrication", true, sp.hasBaseIdTransferRestriction()); + + } + + @Test + public void loadSpWithMsSpecificConfig() throws EaafConfigurationException { + //check + ServiceProviderConfiguration sp = basicConfig.getServiceProviderConfiguration( + "https://demo.egiz.gv.at/junit_test", ServiceProviderConfiguration.class); + + //validate state + Assert.assertNotNull("spConfig", sp); + Assert.assertEquals("friendlyName", "jUnit test", sp.getFriendlyName()); + Assert.assertEquals("UniqueId", "https://demo.egiz.gv.at/junit_test", sp.getUniqueIdentifier()); + Assert.assertEquals("BaseId restrication", true, sp.hasBaseIdTransferRestriction()); + Assert.assertEquals("generic config value", false, + sp.isConfigurationValue("policy.allowed.requested.targets")); + Assert.assertEquals("generic config value", "test", + sp.getConfigurationValue("policy.allowed.requested.targets")); + Assert.assertEquals("not_exist_value", "true", sp.getConfigurationValue("not.exist", "true")); + + } +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/controller/ProcessEngineSignalControllerTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/controller/ProcessEngineSignalControllerTest.java new file mode 100644 index 00000000..d2c4aff2 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/controller/ProcessEngineSignalControllerTest.java @@ -0,0 +1,77 @@ +package at.asitplus.eidas.specific.connector.test.controller; + +import java.io.IOException; +import java.net.URISyntaxException; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +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 at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/applicationContext.xml", + "/specific_eIDAS_connector.beans.xml", + "/eaaf_core.beans.xml", + "/eaaf_pvp.beans.xml", + "/eaaf_pvp_idp.beans.xml", + "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) +@WebAppConfiguration +public class ProcessEngineSignalControllerTest { + + @Autowired private ProcessEngineSignalController controller; + + private MockHttpServletRequest httpReq; + private MockHttpServletResponse httpResp; + + @BeforeClass + public static void classInitializer() { + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_1.properties"); + + } + + /** + * jUnit test set-up. + */ + @Before + public void setUp() throws EaafStorageException, URISyntaxException { + httpReq = new MockHttpServletRequest("POST", "https://localhost/authhandler"); + httpResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + + } + + @Test + public void noPendingRequestId() throws IOException, EaafException { + //set-up + + //execute test + controller.performGenericAuthenticationProcess(httpReq, httpResp); + + //validate state + Assert.assertEquals("http StatusCode", 302, httpResp.getStatus()); + Assert.assertNotNull("redirect header", httpResp.getHeaderValue("Location")); + Assert.assertTrue("wrong redirect header", + httpResp.getHeader("Location").startsWith("http://localhost/errorHandling?errorid=")); + + } + + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java new file mode 100644 index 00000000..b04a5bdb --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorNoEndpointTest.java @@ -0,0 +1,70 @@ +package at.asitplus.eidas.specific.connector.test.health; + +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/spring/SpringTest-context_healthcheck.xml" }) +@TestPropertySource(locations = {"classpath:/config/junit_config_2_springboot.properties"}) +@WebAppConfiguration +public class EidasNodeMetadataHealthIndicatorNoEndpointTest { + + @Autowired EidasNodeMetadataHealthIndicator health; + + private static MockWebServer mockWebServer = null; + + /** + * Testclass initializer. + * + * @throws IOException In case of an error + */ + @BeforeClass + public static void classInitializer() throws IOException { + mockWebServer = new MockWebServer(); + mockWebServer.start(40900); + mockWebServer.url("/mockup"); + + } + + @AfterClass + public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException, IOException { + mockWebServer.shutdown(); + + } + + @Test + public void noEndpointInConfiguration() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorNoEndpointTest.class + .getResourceAsStream("/config/log4j.properties"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.unknown().build().getStatus(), status.getStatus()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java new file mode 100644 index 00000000..b044d4d2 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/health/EidasNodeMetadataHealthIndicatorTest.java @@ -0,0 +1,102 @@ +package at.asitplus.eidas.specific.connector.test.health; + +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; + +import at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/spring/SpringTest-context_healthcheck.xml" }) +@TestPropertySource(locations = {"classpath:/config/junit_config_1_springboot.properties"}) +@WebAppConfiguration +public class EidasNodeMetadataHealthIndicatorTest { + + @Autowired EidasNodeMetadataHealthIndicator health; + + private static MockWebServer mockWebServer = null; + + /** + * Testclass initializer. + * + * @throws IOException In case of an error + */ + @BeforeClass + public static void classInitializer() throws IOException { + mockWebServer = new MockWebServer(); + mockWebServer.start(40900); + mockWebServer.url("/mockup"); + + } + + @AfterClass + public static void resetTestEnviroment() throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException, IOException { + mockWebServer.shutdown(); + + } + + @Test + public void httpStatusCode500() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(500) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus()); + + } + + @Test + public void httpStatusCode200() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/data/metadata_valid.xml"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.up().build().getStatus(), status.getStatus()); + + } + + @Test + public void noXmlResponse() throws IOException { + //set-up status + mockWebServer.enqueue(new MockResponse().setResponseCode(200) + .setBody(IOUtils.toString(EidasNodeMetadataHealthIndicatorTest.class + .getResourceAsStream("/config/log4j.properties"), "UTF-8")) + .setHeader("Content-Type", MediaType.APPLICATION_XML)); + + //perform test + Health status = health.health(); + + //validate state + Assert.assertEquals("wrong healthState", Health.down().build().getStatus(), status.getStatus()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/saml2/Pvp2SProfileEndPointTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/saml2/Pvp2SProfileEndPointTest.java new file mode 100644 index 00000000..bcba3e11 --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/saml2/Pvp2SProfileEndPointTest.java @@ -0,0 +1,337 @@ +package at.asitplus.eidas.specific.connector.test.saml2; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.Timer; + +import javax.xml.transform.TransformerException; + +import org.joda.time.DateTime; +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.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; +import org.opensaml.core.xml.io.MarshallingException; +import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.core.xml.util.XMLObjectSupport; +import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; +import org.opensaml.saml.saml2.core.RequestAbstractType; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml.saml2.metadata.IDPSSODescriptor; +import org.opensaml.saml.saml2.metadata.RoleDescriptor; +import org.opensaml.saml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml.security.impl.SAMLSignatureProfileValidator; +import org.opensaml.security.credential.Credential; +import org.opensaml.security.x509.BasicX509Credential; +import org.opensaml.xmlsec.signature.support.SignatureException; +import org.opensaml.xmlsec.signature.support.SignatureValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ResourceLoader; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +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.util.Base64Utils; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.asitplus.eidas.specific.connector.controller.Pvp2SProfileEndpoint; +import at.asitplus.eidas.specific.connector.provider.PvpEndPointCredentialProvider; +import at.asitplus.eidas.specific.connector.provider.PvpMetadataProvider; +import at.gv.egiz.eaaf.core.api.IRequest; +import at.gv.egiz.eaaf.core.api.IRequestStorage; +import at.gv.egiz.eaaf.core.exceptions.EaafException; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.OpenSaml3ResourceAdapter; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.xml.XMLParserException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({ + "/applicationContext.xml", + "/specific_eIDAS_connector.beans.xml", + "/eaaf_core.beans.xml", + "/eaaf_pvp.beans.xml", + "/eaaf_pvp_idp.beans.xml", + "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) +@WebAppConfiguration +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) +public class Pvp2SProfileEndPointTest { + + + @Autowired private Pvp2SProfileEndpoint controller; + @Autowired private PvpEndPointCredentialProvider credentialProvider; + @Autowired private PvpMetadataProvider metadataProvider; + @Autowired private ResourceLoader resourceLoader; + @Autowired private IRequestStorage storage; + + private static CertificateFactory fact; + + + private MockHttpServletRequest httpReq; + private MockHttpServletResponse httpResp; + + + /** + * jUnit class initializer. + * @throws ComponentInitializationException In case of an error + * @throws InitializationException In case of an error + * @throws CertificateException + * + */ + @BeforeClass + public static void classInitializer() throws InitializationException, + ComponentInitializationException, CertificateException { + final String current = new java.io.File(".").toURI().toString(); + System.setProperty("eidas.ms.configuration", current + "src/test/resources/config/junit_config_1.properties"); + + EaafOpenSaml3xInitializer.eaafInitialize(); + + fact = CertificateFactory.getInstance("X.509"); + + } + + /** + * jUnit test set-up. + * @throws EaafException + * + */ + @Before + public void initialize() throws EaafException { + httpReq = new MockHttpServletRequest("POST", "https://localhost/ms_connector"); + httpResp = new MockHttpServletResponse(); + RequestContextHolder.resetRequestAttributes(); + RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(httpReq, httpResp)); + + } + + @Test + public void authnReqWrongEndpoint() throws EaafException, XMLParserException, UnmarshallingException, + UnsupportedEncodingException, TransformerException, IOException, MarshallingException, + ComponentInitializationException { + //initialize test + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_3.xml")); + authnReq.setIssueInstant(DateTime.now()); + RequestAbstractType signedAuthnReq = + Saml2Utils.signSamlObject(authnReq, credentialProvider.getMetaDataSigningCredential(), true); + String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( + XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8")); + httpReq.setParameter("SAMLRequest", b64); + + final org.springframework.core.io.Resource resource = resourceLoader.getResource( + "classpath:/data/metadata_valid.xml"); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); + + + //request SAML2 authentication + try { + controller.pvpIdpPostRequest(httpReq, httpResp); + Assert.fail("wrong AuthnRequest not detected"); + + }catch (EaafException e) { + Assert.assertEquals("wrong errorId", "pvp2.22", e.getErrorId()); + + } + } + + @Test + public void authnReqWrongSigned() throws EaafException, XMLParserException, UnmarshallingException, + UnsupportedEncodingException, TransformerException, IOException, MarshallingException, + ComponentInitializationException { + //initialize test + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + RequestAbstractType signedAuthnReq = + Saml2Utils.signSamlObject(authnReq, credentialProvider.getMetaDataSigningCredential(), true); + String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( + XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8")); + httpReq.setParameter("SAMLRequest", b64); + + final org.springframework.core.io.Resource resource = resourceLoader.getResource( + "classpath:/data/metadata_valid.xml"); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); + + + //request SAML2 authentication + try { + controller.pvpIdpPostRequest(httpReq, httpResp); + Assert.fail("wrong AuthnRequest not detected"); + + }catch (EaafException e) { + Assert.assertEquals("wrong errorId", "pvp2.21", e.getErrorId()); + + } + } + + @Test + public void authnReqMetadataExpired() throws EaafException, XMLParserException, UnmarshallingException, + UnsupportedEncodingException, TransformerException, IOException, MarshallingException, + ComponentInitializationException { + //initialize test + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + RequestAbstractType signedAuthnReq = + Saml2Utils.signSamlObject(authnReq, credentialProvider.getMetaDataSigningCredential(), true); + String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( + XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8")); + httpReq.setParameter("SAMLRequest", b64); + + final org.springframework.core.io.Resource resource = resourceLoader.getResource( + "classpath:/data/metadata_expired.xml"); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); + + + //request SAML2 authentication + try { + controller.pvpIdpPostRequest(httpReq, httpResp); + Assert.fail("wrong AuthnRequest not detected"); + + }catch (EaafException e) { + Assert.assertEquals("wrong errorId", "pvp2.21", e.getErrorId()); + + } + } + + @Test + public void authnReqValid() throws EaafException, XMLParserException, UnmarshallingException, + UnsupportedEncodingException, TransformerException, IOException, MarshallingException, + ComponentInitializationException { + //initialize test + final RequestAbstractType authnReq = (RequestAbstractType) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + Pvp2SProfileEndPointTest.class.getResourceAsStream("/data/pvp2_authn_1.xml")); + authnReq.setIssueInstant(DateTime.now()); + RequestAbstractType signedAuthnReq = + Saml2Utils.signSamlObject(authnReq, credentialProvider.getMessageSigningCredential(), true); + String b64 = Base64Utils.encodeToString(DomUtils.serializeNode( + XMLObjectSupport.getMarshaller(signedAuthnReq).marshall(signedAuthnReq)).getBytes("UTF-8")); + httpReq.setParameter("SAMLRequest", b64); + + final org.springframework.core.io.Resource resource = resourceLoader.getResource( + "classpath:/data/metadata_valid.xml"); + Timer timer = new Timer("PVP metadata-resolver refresh"); + ResourceBackedMetadataResolver fileSystemResolver = + new ResourceBackedMetadataResolver(timer, new OpenSaml3ResourceAdapter(resource)); + fileSystemResolver.setId("test"); + fileSystemResolver.setParserPool(XMLObjectProviderRegistrySupport.getParserPool()); + fileSystemResolver.initialize(); + metadataProvider.addMetadataResolverIntoChain(fileSystemResolver); + + + //request SAML2 authentication + controller.pvpIdpPostRequest(httpReq, httpResp); + + + //validate state + Assert.assertEquals("http statuscode", 200, httpResp.getStatus()); + Assert.assertEquals("Wrong http ContentType", "text/html;charset=UTF-8", httpResp.getContentType()); + + String html = httpResp.getContentAsString(); + Assert.assertNotNull("html result is null", html); + Assert.assertFalse("html result is empty", html.isEmpty()); + Assert.assertTrue("Wrong page", html.contains("action=\"/myHomeCountry\"")); + + String pattern = "<input type=\"hidden\" name=\"pendingid\" value=\""; + int pendingIdStart = html.indexOf(pattern) + pattern.length(); + int pendingIdEnd = html.indexOf("\"", pendingIdStart); + String pendingReqId = html.substring(pendingIdStart, pendingIdEnd); + Assert.assertFalse("pendingReqId is empty", pendingReqId.isEmpty()); + + IRequest pendingReq = storage.getPendingRequest(pendingReqId); + Assert.assertNotNull("pendingReq", pendingReq); + Assert.assertNotNull("piiTransId", pendingReq.getUniquePiiTransactionIdentifier()); + Assert.assertNotNull("piiTransId", pendingReq.getUniqueTransactionIdentifier()); + + Assert.assertEquals("wrong OA Id", "https://demo.egiz.gv.at/demoportal-openID_demo", + pendingReq.getRawData(MsEidasNodeConstants.DATA_REQUESTERID, String.class)); + Assert.assertEquals("wrong bPK Target", "urn:publicid:gv.at:cdid+BF", + pendingReq.getServiceProviderConfiguration().getAreaSpecificTargetIdentifier()); + + + } + + @Test + public void checkSaml2Metadata() throws EaafException, UnsupportedEncodingException, XMLParserException, + UnmarshallingException, CertificateException, SignatureException { + + //request SAML2 Metadata + controller.pvpMetadataRequest(httpReq, httpResp); + + //validate state + Assert.assertEquals("http statuscode", 200, httpResp.getStatus()); + Assert.assertEquals("Wrong http ContentType", "application/xml", httpResp.getContentType()); + + String html = httpResp.getContentAsString(); + Assert.assertNotNull("html result is null", html); + Assert.assertFalse("html result is empty", html.isEmpty()); + + + final EntityDescriptor entity = (EntityDescriptor) XMLObjectSupport.unmarshallFromInputStream( + XMLObjectProviderRegistrySupport.getParserPool(), + new ByteArrayInputStream(html.getBytes("UTF-8"))); + + Assert.assertNotNull("Unmarshalling failed", entity); + Assert.assertNotNull("EntityId is null", entity.getEntityID()); + + Assert.assertNotNull("Signature is null", entity.getSignature()); + final SAMLSignatureProfileValidator sigValidator = new SAMLSignatureProfileValidator(); + sigValidator.validate(entity.getSignature()); + + final Credential cred = new BasicX509Credential((X509Certificate) fact.generateCertificate( + Pvp2SProfileEndPointTest.class.getResourceAsStream("/config/keys/Metadata.pem"))); + SignatureValidator.validate(entity.getSignature(), cred); + + Assert.assertEquals("wrong entityId", "http://localhost/pvp/metadata", entity.getEntityID()); + Assert.assertNotNull("IDPSSODescr", entity.getRoleDescriptors(IDPSSODescriptor.DEFAULT_ELEMENT_NAME)); + Assert.assertNotNull("SPSSODescr", entity.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME)); + Assert.assertEquals("SPSSODescr. size", 0, + entity.getRoleDescriptors(SPSSODescriptor.DEFAULT_ELEMENT_NAME).size()); + + List<RoleDescriptor> idp = entity.getRoleDescriptors(IDPSSODescriptor.DEFAULT_ELEMENT_NAME); + Assert.assertEquals("IDP descr. size", 1, idp.size()); + Assert.assertEquals("IDP descr. endpoints", 2, idp.get(0).getEndpoints().size()); + Assert.assertEquals("IDP descr. keyDescr", 1, idp.get(0).getKeyDescriptors().size()); + + } + +} diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/EvaluateCountrySelectionTaskTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/EvaluateCountrySelectionTaskTest.java index 9d590055..4bff9416 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/EvaluateCountrySelectionTaskTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/EvaluateCountrySelectionTaskTest.java @@ -12,6 +12,7 @@ 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; @@ -34,6 +35,7 @@ import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) @WebAppConfiguration public class EvaluateCountrySelectionTaskTest { diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/GenerateCountrySelectionFrameTaskTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/GenerateCountrySelectionFrameTaskTest.java index 2a1d7cd4..d902f758 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/GenerateCountrySelectionFrameTaskTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/task/GenerateCountrySelectionFrameTaskTest.java @@ -13,6 +13,7 @@ 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; @@ -32,6 +33,7 @@ import at.gv.egiz.eaaf.core.impl.idp.process.ExecutionContextImpl; "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) @WebAppConfiguration public class GenerateCountrySelectionFrameTaskTest { diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java new file mode 100644 index 00000000..5f1c5dcf --- /dev/null +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthenticationDataBuilderTest.java @@ -0,0 +1,354 @@ +package at.asitplus.eidas.specific.connector.test.utils; + +import static at.asitplus.eidas.specific.connector.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.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.connector.builder.AuthenticationDataBuilder; +import at.asitplus.eidas.specific.modules.auth.eidas.v2.Constants; +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.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.idp.auth.builder.BpkBuilder; +import at.gv.egiz.eaaf.core.impl.idp.auth.data.AuthProcessDataWrapper; +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({ "/applicationContext.xml", "/spring/SpringTest_connector.beans.xml", "/eaaf_core.beans.xml", + "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) +@WebAppConfiguration +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<String, String> 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(Constants.SZR_AUTHBLOCK, authBlock); + pendingReq.getSessionData(AuthProcessDataWrapper.class) + .setGenericDataToSession(Constants.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 + pendingReq.getSessionData(AuthProcessDataWrapper.class).setEidProcess(true); + + // execute + IAuthData authData = authenticationDataBuilder.buildAuthenticationData(pendingReq); + + // validate state + Assert.assertNotNull("AuthData null", authData); + Assert.assertNotNull("authBlock null", authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class)); + Assert.assertNotNull("eidasBind null", authData.getGenericData(Constants.EIDAS_BIND, String.class)); + Assert.assertNotNull("LoA null", authData.getEidasQaaLevel()); + + String authBlock = authData.getGenericData(Constants.SZR_AUTHBLOCK, String.class); + String eidasBind = authData.getGenericData(Constants.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 + 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(Constants.SZR_AUTHBLOCK, String.class)); + Assert.assertNull("eidasBind null", authData.getGenericData(Constants.EIDAS_BIND, String.class)); + Assert.assertNull("piiTransactionId", + authData.getGenericData(ExtendedPvpAttributeDefinitions.EID_PII_TRANSACTION_ID_NAME, String.class)); + + + 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.getFormatedDateOfBirth()); + 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/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthnRequestValidatorTest.java index 389f561e..9aafb4b6 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/AuthnRequestValidatorTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/AuthnRequestValidatorTest.java @@ -1,4 +1,4 @@ -package at.asitplus.eidas.specific.connector.test; +package at.asitplus.eidas.specific.connector.test.utils; import java.io.IOException; import java.util.HashMap; @@ -22,6 +22,7 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext.ClassMode; +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; @@ -52,6 +53,7 @@ import net.shibboleth.utilities.java.support.component.ComponentInitializationEx "/eaaf_pvp.beans.xml", "/eaaf_pvp_idp.beans.xml", "/spring/SpringTest-context_simple_storage.xml" }) +@ActiveProfiles(profiles = {"deprecatedConfig"}) @WebAppConfiguration @DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class AuthnRequestValidatorTest { diff --git a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/CountrySelectionProcessImplTest.java b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/CountrySelectionProcessImplTest.java index 455288f5..d0343eba 100644 --- a/connector/src/test/java/at/asitplus/eidas/specific/connector/test/CountrySelectionProcessImplTest.java +++ b/connector/src/test/java/at/asitplus/eidas/specific/connector/test/utils/CountrySelectionProcessImplTest.java @@ -1,4 +1,4 @@ -package at.asitplus.eidas.specific.connector.test; +package at.asitplus.eidas.specific.connector.test.utils; import java.util.HashMap; import java.util.Map; diff --git a/connector/src/test/resources/config/junit_config_1.properties b/connector/src/test/resources/config/junit_config_1.properties index 3350f947..f6b3e4c1 100644 --- a/connector/src/test/resources/config/junit_config_1.properties +++ b/connector/src/test/resources/config/junit_config_1.properties @@ -1,6 +1,7 @@ ## Basic service configuration eidas.ms.context.url.prefix=http://localhost eidas.ms.context.url.request.validation=false +eidas.ms.core.configRootDir=file:./src/test/resources/config/ eidas.ms.context.use.clustermode=true @@ -97,19 +98,27 @@ 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.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= +eidas.ms.sp.0.friendlyName=jUnit test #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 + ##only for advanced config eidas.ms.configuration.sp.disableRegistrationRequirement= -eidas.ms.configuration.restrictions.baseID.spTransmission= +#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/connector/src/test/resources/config/junit_config_1_springboot.properties b/connector/src/test/resources/config/junit_config_1_springboot.properties new file mode 100644 index 00000000..e63cda7b --- /dev/null +++ b/connector/src/test/resources/config/junit_config_1_springboot.properties @@ -0,0 +1,83 @@ +## embbeded Tomcat +tomcat.workingdir=./target/work +tomcat.ajp.enabled=true +tomcat.ajp.port=8009 +tomcat.ajp.networkAddress=127.0.0.1 +tomcat.ajp.additionalAttributes.secretrequired=true +tomcat.ajp.additionalAttributes.secret=junit + +## Basic service configuration +eidas.ms.context.url.prefix=http://localhost +eidas.ms.core.configRootDir=file:./src/test/resources/config/ + +eidas.ms.context.use.clustermode=true + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url=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 + diff --git a/connector/src/test/resources/config/junit_config_2_springboot.properties b/connector/src/test/resources/config/junit_config_2_springboot.properties new file mode 100644 index 00000000..ecb22dec --- /dev/null +++ b/connector/src/test/resources/config/junit_config_2_springboot.properties @@ -0,0 +1,83 @@ +## embbeded Tomcat +tomcat.workingdir=./target/work +tomcat.ajp.enabled=true +tomcat.ajp.port=8009 +tomcat.ajp.networkAddress=127.0.0.1 +tomcat.ajp.additionalAttributes.secretrequired=true +tomcat.ajp.additionalAttributes.secret=junit + +## Basic service configuration +eidas.ms.context.url.prefix=http://localhost +eidas.ms.core.configRootDir=file:./src/test/resources/config/ + +eidas.ms.context.use.clustermode=true + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + +## eIDAS Ref. Implementation connector ### +eidas.ms.auth.eIDAS.node_v2.forward.endpoint=http://eidas.node/junit + +eidas.ms.auth.eIDAS.szrclient.useTestService=true +eidas.ms.auth.eIDAS.szrclient.endpoint.prod= +eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks +eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= +eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= + +#tech. AuthBlock signing for E-ID process +eidas.ms.auth.eIDAS.authblock.keystore.password=f/+saJBc3a}*/T^s +eidas.ms.auth.eIDAS.authblock.keystore.friendlyName=connectorkeypair +eidas.ms.auth.eIDAS.authblock.keystore.path=keys/teststore.jks +eidas.ms.auth.eIDAS.authblock.keystore.type=jks +eidas.ms.auth.eIDAS.authblock.key.alias=connectorkeypair +eidas.ms.auth.eIDAS.authblock.key.password=f/+saJBc3a}*/T^s + + +#Raw eIDAS Id data storage +eidas.ms.auth.eIDAS.szrclient.debug.logfullmessages=true +eidas.ms.auth.eIDAS.szrclient.debug.useDummySolution=false + + + +## PVP2 S-Profile end-point configuration +eidas.ms.pvp2.keystore.type=jks +eidas.ms.pvp2.keystore.path=keys/junit.jks +eidas.ms.pvp2.keystore.password=password +eidas.ms.pvp2.key.metadata.alias=meta +eidas.ms.pvp2.key.metadata.password=password +eidas.ms.pvp2.key.signing.alias=sig +eidas.ms.pvp2.key.signing.password=password +eidas.ms.pvp2.metadata.validity=24 + +eidas.ms.pvp2.metadata.organisation.name=JUnit +eidas.ms.pvp2.metadata.organisation.friendyname=For testing with jUnit +eidas.ms.pvp2.metadata.organisation.url=http://junit.test +eidas.ms.pvp2.metadata.contact.givenname=Max +eidas.ms.pvp2.metadata.contact.surname=Mustermann +eidas.ms.pvp2.metadata.contact.email=max@junit.test + +## Service Provider configuration +eidas.ms.sp.0.uniqueID=https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata +eidas.ms.sp.0.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.0.pvp2.metadata.truststore.password=password +eidas.ms.sp.0.friendlyName=jUnit test +eidas.ms.sp.0.newEidMode=true + +#eidas.ms.sp.0.pvp2.metadata.url= +#eidas.ms.sp.0.policy.allowed.requested.targets=.* +#eidas.ms.sp.0.policy.hasBaseIdTransferRestriction=false + +## Service Provider configuration +eidas.ms.sp.1.uniqueID=https://demo.egiz.gv.at/junit_test +eidas.ms.sp.1.pvp2.metadata.truststore=keys/junit.jks +eidas.ms.sp.1.pvp2.metadata.truststore.password=password +eidas.ms.sp.1.friendlyName=jUnit test +eidas.ms.sp.1.pvp2.metadata.url=http://junit.test/metadata +eidas.ms.sp.1.policy.allowed.requested.targets=test +eidas.ms.sp.1.policy.hasBaseIdTransferRestriction=true + diff --git a/connector/src/test/resources/config/junit_config_3.properties b/connector/src/test/resources/config/junit_config_3.properties index 32e30790..8b2c63a8 100644 --- a/connector/src/test/resources/config/junit_config_3.properties +++ b/connector/src/test/resources/config/junit_config_3.properties @@ -1,6 +1,7 @@ ## Basic service configuration eidas.ms.context.url.prefix= eidas.ms.context.url.request.validation=false +eidas.ms.core.configRootDir=file:./src/test/resources/config/ eidas.ms.context.use.clustermode=true diff --git a/connector/src/test/resources/config/keys/Metadata.pem b/connector/src/test/resources/config/keys/Metadata.pem new file mode 100644 index 00000000..b544c194 --- /dev/null +++ b/connector/src/test/resources/config/keys/Metadata.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIIC+jCCAeKgAwIBAgIEXjF+fTANBgkqhkiG9w0BAQsFADA/MQswCQYDVQQGEwJB +VDENMAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxETAPBgNVBAMMCE1ldGFk +YXRhMB4XDTIwMDEyOTEyNDU0OVoXDTI2MDEyODEyNDU0OVowPzELMAkGA1UEBhMC +QVQxDTALBgNVBAcMBEVHSVoxDjAMBgNVBAoMBWpVbml0MREwDwYDVQQDDAhNZXRh +ZGF0YTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK230G3dxNbNlSYA +O5Kx/Js0aBAgxMt7q9m+dA35fK/dOvF/GjrqjWsMCnax+no9gLnq6x0gXiJclz6H +rp/YDOfLrJjMpNL/r0FWT947vbnEj7eT8TdY5d6Yi8AZulZmjiCI5nbZh2zwrP4+ +WqRroLoPhXQj8mDyp26M4xHBBUhLMRc2HV4S+XH4uNZ/vTmb8vBg31XGHCY33gl7 +/KA54JNGxJdN8Dxv6yHYsm91ZfVrX39W0iYLUNhUCkolwuQmjDVfrExM8BTLIONb +f+erJoCm3A9ghZyDYRQ/e69/UEUqDa6XOzykr88INkQscEiAXCDS+EBPMpKo+t3l +PIA9r7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAh/2mg4S03bdZy1OVtEAudBT9 +YZb9OF34hxPtNbkB/V04wSIg1d4TBr5KDhV7CdiUOxPZzHpS8LUCgfGX306FB6NX +zh/b67uTOPaE72AB4VIT/Np0fsM7k5WhG9k9NoprIGiqCz2lXcfpZiT+LtSO1vWS +YI87wR9KOSWjcw/5i5qZIAJuwvLCQj5JtUsmrhHK75222J3TJf4dS/gfN4xfY2rW +9vcXtH6//8WdWp/zx9V7Z1ZsDb8TDKtBCEGuFDgVeU5ScKtVq8qRoUKD3Ve76cZi +purO3KrRrVAuZP2EfLkZdHEHqe8GPigNnZ5kTn8V2VJ3iRAQ73hpJRR98tFd0A== +-----END CERTIFICATE----- diff --git a/connector/src/test/resources/config/keys/teststore.jks b/connector/src/test/resources/config/keys/teststore.jks Binary files differnew file mode 100644 index 00000000..fcc6400c --- /dev/null +++ b/connector/src/test/resources/config/keys/teststore.jks diff --git a/connector/src/test/resources/config/templates/error_message.html b/connector/src/test/resources/config/templates/error_message.html index da423592..86f9d29d 100644 --- a/connector/src/test/resources/config/templates/error_message.html +++ b/connector/src/test/resources/config/templates/error_message.html @@ -21,8 +21,8 @@ <div id="alert_area" class="hell" role="application" > <p th:text="#{gui.errorpage.msg.information}">Error Information</p> <br/> - <p><b th:text="#{gui.errorpage.msg.errorcode}">Code :</b> <span th:text="${msg.errorCode}"></span></p> - <p><b th:text="#{gui.errorpage.msg.errormsg}">Msg :</b > <span th:text="${#messages.msgWithParams('__${msg.errorCode}__', '__${msg.errorParams}__')}"></span></p> + <p><b th:text="#{gui.errorpage.msg.errorcode}">Code :</b> <span th:text="${errorCode}"></span></p> + <p><b th:text="#{gui.errorpage.msg.errormsg}">Msg :</b > <span th:text="${#messages.msgWithParams('__${errorCode}__', '__${errorParams}__')}"></span></p> </div> <!-- errorMsg --> </div> diff --git a/connector/src/test/resources/data/metadata_expired.xml b/connector/src/test/resources/data/metadata_expired.xml new file mode 100644 index 00000000..16364c05 --- /dev/null +++ b/connector/src/test/resources/data/metadata_expired.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b67c160c0ad7b4ebd430581df167ac23" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata" validUntil="2020-12-12T20:41:20.635Z"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_b67c160c0ad7b4ebd430581df167ac23"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>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=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>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=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/connector/src/test/resources/data/metadata_valid.xml b/connector/src/test/resources/data/metadata_valid.xml new file mode 100644 index 00000000..06e1e785 --- /dev/null +++ b/connector/src/test/resources/data/metadata_valid.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b67c160c0ad7b4ebd430581df167ac23" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_b67c160c0ad7b4ebd430581df167ac23"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>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=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:KeyDescriptor use="encryption"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>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=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/connector/src/test/resources/data/metadata_valid_without_encryption.xml b/connector/src/test/resources/data/metadata_valid_without_encryption.xml new file mode 100644 index 00000000..b224c336 --- /dev/null +++ b/connector/src/test/resources/data/metadata_valid_without_encryption.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_b67c160c0ad7b4ebd430581df167ac23" entityID="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata"> + <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:SignedInfo> + <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/> + <ds:Reference URI="#_b67c160c0ad7b4ebd430581df167ac23"> + <ds:Transforms> + <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> + <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> + </ds:Transforms> + <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/> + <ds:DigestValue>00SaL0XjeknOb/DttutP50lTyAux1jaRPJIVdSupWvU=</ds:DigestValue> + </ds:Reference> + </ds:SignedInfo> + <ds:SignatureValue>PfEBmLMX/ZgL6ViXghyWtal5MaMoW8k3zjw+54+WK1OAtVsVgOsIDRJE0M/a/VXBbMSifgY6J1gN23xhr61jkrjRQEkbDzLpWZLzWAJ65YqqUQo8wsKI2Gz0j12yY5D8/GOamKOH9KDi5ba1veXR/fnxRINoy7nZo4tcUWZChdl8BWkMN5ugr6dORNIQg/Ym3GabQ/hR5z+9FmveAKphdH63MC6qW3EgM9EMvOVkrLBTP92sNMAAJeaawui9tlxi9anVQ0OqwZsgKLvI7fyV4CM/0sd/ELjeReIlWlHk07Nz4eltMq3eOx3q1YurYvhE8XapHiQMehOtCS+Fzh10sw==</ds:SignatureValue> + <ds:KeyInfo> + <ds:X509Data> + <ds:X509Certificate>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=</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </ds:Signature> + <md:SPSSODescriptor AuthnRequestsSigned="true" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> + <md:KeyDescriptor use="signing"> + <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> + <ds:X509Data> + <ds:X509Certificate>MIIBbTCCARKgAwIBAgIEXjF+qTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +HhcNMjAwMTI5MTI0NjMzWhcNMjcwMTI4MTI0NjMzWjA+MQswCQYDVQQGEwJBVDEN +MAsGA1UEBwwERUdJWjEOMAwGA1UECgwFalVuaXQxEDAOBgNVBAMMB3NpZ25pbmcw +WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASRt7gZRrr4rSEE7Q922oKQJF+mlkwC +LZnv8ZzHtH54s4VdyQFIBjQF1PPf9PTn+5tid8QJehZPndcoeD7J8fPJMAoGCCqG +SM49BAMCA0kAMEYCIQDFUO0owvqMVRO2FmD+vb8mqJBpWCE6Cl5pEHaygTa5LwIh +ANsmjI2azWiTSFjb7Ou5fnCfbeiJUP0s66m8qS4rYl9L</ds:X509Certificate> + </ds:X509Data> + </ds:KeyInfo> + </md:KeyDescriptor> + <md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</md:NameIDFormat> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/post" index="0" isDefault="true"/> + <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/redirect" index="1"/> + <md:AttributeConsumingService index="0" isDefault="true"> + <md:ServiceName xml:lang="en">Default Service</md:ServiceName> + <md:RequestedAttribute FriendlyName="BPK" Name="urn:oid:1.2.40.0.10.2.1.1.149" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="PRINCIPAL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.20" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="BIRTHDATE" Name="urn:oid:1.2.40.0.10.2.1.1.55" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="PVP-VERSION" Name="urn:oid:1.2.40.0.10.2.1.1.261.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="EID-ISSUING-NATION" Name="urn:oid:1.2.40.0.10.2.1.1.261.32" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.76" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-FULL-NAME" Name="urn:oid:1.2.40.0.10.2.1.1.261.84" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE" Name="urn:oid:1.2.40.0.10.2.1.1.261.68" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATOR-LEGAL-PERSON-SOURCE-PIN" Name="urn:oid:1.2.40.0.10.2.1.1.261.100" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="GIVEN-NAME" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-SECTOR-FOR-IDENTIFIER" Name="urn:oid:1.2.40.0.10.2.1.1.261.34" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="MANDATE-TYPE-OID" Name="urn:oid:1.2.40.0.10.2.1.1.261.106" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-IDENTITY-LINK" Name="urn:oid:1.2.40.0.10.2.1.1.261.38" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="EID-CITIZEN-QAA-EIDAS-LEVEL" Name="urn:oid:1.2.40.0.10.2.1.1.261.108" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true"/> + <md:RequestedAttribute FriendlyName="userAuthBlock" Name="urn:eidgvat:attributes.authblock.signed" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="eidBind" Name="urn:eidgvat:attributes.eidbind" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + <md:RequestedAttribute FriendlyName="piiTransactionId" Name="urn:eidgvat:attributes.piiTransactionId" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false"/> + </md:AttributeConsumingService> + </md:SPSSODescriptor> + <md:Organization> + <md:OrganizationName xml:lang="de">EGIZ</md:OrganizationName> + <md:OrganizationDisplayName xml:lang="de">E-Government Innovationszentrum</md:OrganizationDisplayName> + <md:OrganizationURL xml:lang="de">http://www.egiz.gv.at</md:OrganizationURL> + </md:Organization> + <md:ContactPerson contactType="technical"> + <md:Company>E-Government Innovationszentrum</md:Company> + <md:GivenName>Lenz</md:GivenName> + <md:SurName>Thomas</md:SurName> + <md:EmailAddress>thomas.lenz@egiz.gv.at</md:EmailAddress> + <md:TelephoneNumber>+43 316 873 5525</md:TelephoneNumber> + </md:ContactPerson> +</md:EntityDescriptor> diff --git a/connector/src/test/resources/data/pvp2_authn_1.xml b/connector/src/test/resources/data/pvp2_authn_1.xml index ff5f08a5..1275b200 100644 --- a/connector/src/test/resources/data/pvp2_authn_1.xml +++ b/connector/src/test/resources/data/pvp2_authn_1.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="0" Destination="https://vidp.gv.at/ms_connector/pvp/post" ID="_27f4ce57e524e483446654a34cf886e2" IsPassive="false" IssueInstant="2019-12-11T10:50:19.032Z" ProviderName="OpenID Connect Demo" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> +<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceIndex="0" Destination="http://localhost/pvp/post" ID="_27f4ce57e524e483446654a34cf886e2" IsPassive="false" IssueInstant="2019-12-11T10:50:19.032Z" ProviderName="OpenID Connect Demo" Version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://demo.egiz.gv.at/demoportal_moaid-2.0/sp/eidas/metadata</saml2:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> diff --git a/connector/src/test/resources/data/test_idl_1.xml b/connector/src/test/resources/data/test_idl_1.xml new file mode 100644 index 00000000..8151468b --- /dev/null +++ b/connector/src/test/resources/data/test_idl_1.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID1467616845518699" IssueInstant="2016-07-04T09:20:45+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0"> + <saml:AttributeStatement> + <saml:Subject> + <saml:SubjectConfirmation> + <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> + <saml:SubjectConfirmationData> + <pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>AT/CZ/xWE0vFWarzpzSL4LYlpst9b6vg0=</pr:Value><pr:Type>urn:publicid:gv.at:eidasid+AT+CZ</pr:Type></pr:Identification><pr:Name><pr:GivenName>XXXMaria-Theresia Kunigunda</pr:GivenName><pr:FamilyName primary="undefined">XXXHabsburg-Lothringen</pr:FamilyName></pr:Name><pr:DateOfBirth>1980-02-29</pr:DateOfBirth></pr:Person> + </saml:SubjectConfirmationData> + </saml:SubjectConfirmation> + </saml:Subject> + <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="49629022697474602497707473238246914610217535689798527313620157109614355242988" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="77111560713755914450736041751615112402310649832147731609221710465065501356492" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><dsig:RSAKeyValue><dsig:Modulus>1BFOitiQUc1lAHDGksneXWZGKGaFBcu03HEiIFsjHjNt/IfRZ4IzqHotUKItxnCdNtsFc1MkMJg+ +g0AXHsuU6MNgcbcXPaPfmHp+8+BJh+amDF3FnAN4ceG8oFAGVEZteOgfdWk1r5RQ2SK+0PuXPuLp +Tee7IzXtksReZkVEadUCxn/hiRXZa0dABgkFe3kSXbDr5tKXOF0FCtLKhZBI9z+NbX+aTSKOmAOq +4jyymoo5EP3L+iPecrUwHijD0Bm89h1JjxP521fkYe3Si+0J40okrmCCQHBr+IzB1uX98pKhvs7X +6rPjOJ6lBwP7XjK7D128P/cg4eH6v58cCfbLcQ==</dsig:Modulus><dsig:Exponent>AQAB</dsig:Exponent></dsig:RSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement> + +<dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:SignedInfo><dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><dsig:Reference Id="reference-1-1" URI=""><dsig:Transforms><dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><dsig:DigestValue>E+BXH0C2F6EYHjdJrOUKr+DsKT8=</dsig:DigestValue></dsig:Reference></dsig:SignedInfo><dsig:SignatureValue>Hvj40m9ridp2HOz81MTAqzf0q+sZC5YeKpJP43eK5G1HNH1/DNGU/r/6IVPibU9Y +YGYJoXpznxRFibEQ6dFCHAaNPyADmdGHyJSWryI5ypAap4Y8MJnaUGSWY49IZbht +PjfKWB2jUNzj1T2u6ebIifAThAK8ZqIE+e5uaR+qrrLicxIhXcSZoyScbKxMuT1Q +p6zNsNBOHujbVAfKFUE8WmGInyvuoDgerUrA0XstWWg2M9ghytcDJwZpTYwXvmmo +GV47ue0ITrtM+QqWVbt+dHO8369JFnGQ9h/6h/4j9iyNuxfG7u/EyHQiSuy0+FP8 +1lkLsg1YX+2pN0HElyXVqw==</dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>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=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo></dsig:Signature></saml:Assertion>
\ No newline at end of file diff --git a/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml b/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml new file mode 100644 index 00000000..3bac88e3 --- /dev/null +++ b/connector/src/test/resources/spring/SpringTest-context_healthcheck.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:tx="http://www.springframework.org/schema/tx" + xmlns:aop="http://www.springframework.org/schema/aop" + xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + + <context:annotation-config /> + + <import resource="classpath:/SpringTest-context_authManager.xml" /> + + <bean id="basicConfig" + class="at.asitplus.eidas.specific.connector.config.SpringBootBasicConfigurationProvider" /> + + <bean id="eidasNodeMetadata" + class="at.asitplus.eidas.specific.connector.health.EidasNodeMetadataHealthIndicator" /> + +</beans>
\ No newline at end of file diff --git a/connector/src/main/resources/SpringTest_connector.beans.xml b/connector/src/test/resources/spring/SpringTest_connector.beans.xml index 5cf0d5b8..ba385cb9 100644 --- a/connector/src/main/resources/SpringTest_connector.beans.xml +++ b/connector/src/test/resources/spring/SpringTest_connector.beans.xml @@ -21,13 +21,6 @@ <bean id="ProcessEngineSignalController" class="at.asitplus.eidas.specific.connector.controller.ProcessEngineSignalController" /> - <bean id="MonitoringController" - class="at.asitplus.eidas.specific.connector.controller.MonitoringController"> - <property name="pvpIdpCredentials"> - <ref bean="PVPEndPointCredentialProvider" /> - </property> - </bean> - <bean id="AuthenticationManager" class="at.asitplus.eidas.specific.connector.auth.AuthenticationManager" /> |