From 6b098e7070dedb5692325f6d330a20de696b9edc Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Tue, 22 Dec 2020 15:36:42 +0100 Subject: switch from Spring to Spring-Boot --- .../MsSpecificEidasNodeSpringResourceProvider.java | 10 +- ...ficSpringBootApplicationContextInitializer.java | 82 ++++++++ .../SpringBootApplicationInitializer.java | 60 ++++++ .../connector/SpringContextCloseHandler.java | 224 +++++++++++++++++++++ .../config/StaticResourceConfiguration.java | 87 ++++---- .../storage/SimpleInMemoryTransactionStorage.java | 2 - .../src/main/resources/application.properties | 144 +++++++++++++ .../src/main/resources/applicationContext.xml | 23 ++- connector/src/main/resources/log4j.properties | 55 ----- connector/src/main/resources/logback.xml | 20 +- .../resources/specific_eIDAS_connector.beans.xml | 21 +- connector/src/main/resources/tomcat.properties | 15 ++ 12 files changed, 613 insertions(+), 130 deletions(-) create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java create mode 100644 connector/src/main/resources/application.properties delete mode 100644 connector/src/main/resources/log4j.properties create mode 100644 connector/src/main/resources/tomcat.properties (limited to 'connector/src/main') 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..5160bdf5 --- /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..0d3226bf --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java @@ -0,0 +1,60 @@ +package at.asitplus.eidas.specific.connector; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; + +import at.gv.egiz.eaaf.core.impl.logging.LogMessageProviderFactory; +import at.gv.egiz.eaaf.core.impl.logging.SimpleStatusMessager; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@SpringBootApplication(scanBasePackages = {"at.gv.egiz.eaaf.utils.springboot.ajp"}) +public class SpringBootApplicationInitializer { + + private static ConfigurableApplicationContext ctx; + + /** + * Starts MS-specific eIDAS-Implementation SpringBoot application. + * + * @param args Starting parameters + */ + public static void main(final String[] args) { + try { + log.info("=============== Initializing Spring-Boot context! ==============="); + LogMessageProviderFactory.setStatusMessager(new SimpleStatusMessager()); + final SpringApplication springApp = + new SpringApplication(SpringBootApplicationInitializer.class); + springApp.addInitializers(new MsSpecificSpringBootApplicationContextInitializer()); + + log.debug("Run SpringBoot initialization process ... "); + ctx = springApp.run(args); + + log.info("Initialization of MS-specific eIDAS-Implementation finished."); + + } catch (final Throwable e) { + log.error("MS-specific eIDAS-Implementation initialization FAILED!", e); + throw e; + + } + + } + + /** + * 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..2a3b659a --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java @@ -0,0 +1,224 @@ +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, ApplicationContextAware, BeanPostProcessor { + + private static final Logger log = + org.slf4j.LoggerFactory.getLogger(SpringContextCloseHandler.class); + + private ApplicationContext context; + + /* + * (non-Javadoc) + * + * @see org.springframework.context.ApplicationListener#onApplicationEvent(org. + * springframework.context. ApplicationEvent) + */ + @Override + @EventListener + public void onApplicationEvent(final ContextClosedEvent arg0) { + log.info("MS-specific eIDAS-Node shutdown process started ..."); + + try { + log.debug("CleanUp objects with implements the IDestroyable interface ... "); + final Map objectsToDestroy = + context.getBeansOfType(IDestroyableObject.class); + internalIDestroyableObject(objectsToDestroy); + log.info("Object cleanUp complete"); + + log.debug("Stopping Spring Thread-Pools ... "); + // shut-down task schedulers + final Map schedulers = + context.getBeansOfType(ThreadPoolTaskScheduler.class); + internalThreadPoolTaskScheduler(schedulers); + + // shut-down task executors + final Map executers = + context.getBeansOfType(ThreadPoolTaskExecutor.class); + internalThreadPoolTaskExecutor(executers); + log.debug("Spring Thread-Pools stopped"); + + + //clean-up eIDAS node + Map nodeIgnite = + context.getBeansOfType(IgniteInstanceInitializerSpecificCommunication.class); + log.info("Find #{} Apache Ignite instances from eIDAS Ref. impl.", nodeIgnite.size()); + for (Entry el : nodeIgnite.entrySet()) { + if (el.getValue().getInstance() != null) { + el.getValue().getInstance().close(); + el.getValue().destroyInstance(); + log.debug("Shutdown Apache-Ignite: {}", el.getKey()); + + } + } + + log.info("MS-specific eIDAS-Node shutdown process finished"); + + } catch (final Exception e) { + log.warn("MS-specific eIDAS-Node shutdown process has an error.", e); + + } + + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.config.BeanPostProcessor# + * postProcessAfterInitialization(java. lang.Object, java.lang.String) + */ + @Override + public Object postProcessAfterInitialization(final Object arg0, final String arg1) + throws BeansException { + if (arg0 instanceof ThreadPoolTaskScheduler) { + ((ThreadPoolTaskScheduler) arg0).setWaitForTasksToCompleteOnShutdown(true); + } + if (arg0 instanceof ThreadPoolTaskExecutor) { + ((ThreadPoolTaskExecutor) arg0).setWaitForTasksToCompleteOnShutdown(true); + } + return arg0; + + } + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.config.BeanPostProcessor# + * postProcessBeforeInitialization(java .lang.Object, java.lang.String) + */ + @Override + public Object postProcessBeforeInitialization(final Object arg0, final String arg1) + throws BeansException { + return arg0; + + } + + /* + * (non-Javadoc) + * + * @see + * org.springframework.context.ApplicationContextAware#setApplicationContext(org + * .springframework. context.ApplicationContext) + */ + @Override + public void setApplicationContext(final ApplicationContext arg0) throws BeansException { + this.context = arg0; + + } + + private void internalThreadPoolTaskExecutor(final Map executers) { + for (final ThreadPoolTaskExecutor executor : executers.values()) { + // Not needed yet + // int retryCount = 0; + // while(executor.getActiveCount()>0 && ++retryCount<51){ + // try { + // log.debug("Executer {} is still working with active {} work. Retry count is + // {}", + // executor.getThreadNamePrefix(), + // executor.getActiveCount(), + // retryCount); + // Thread.sleep(1000); + // + // } catch (final InterruptedException e) { + // e.printStackTrace(); + // } + // } + // + // if(!(retryCount<51)) + // log.debug("Executer {} is still working. Since Retry count exceeded max value + // {}, will be + // killed immediately", + // executor.getThreadNamePrefix(), + // retryCount); + + executor.shutdown(); + log.debug("Executer {} with active {} work has killed", executor.getThreadNamePrefix(), + executor.getActiveCount()); + + } + + } + + // Not required at the moment + private void internalThreadPoolTaskScheduler( + final Map schedulers) { + log.trace("Stopping #{} task-schedulers", schedulers.size()); + + // for (final ThreadPoolTaskScheduler scheduler : schedulers.values()) { + // scheduler.getScheduledExecutor().shutdown(); + // try { + // scheduler.getScheduledExecutor().awaitTermination(20000, + // TimeUnit.MILLISECONDS); + // if(scheduler.getScheduledExecutor().isTerminated() || + // scheduler.getScheduledExecutor().isShutdown()) + // log.debug("Scheduler {} has stoped", scheduler.getThreadNamePrefix()); + // + // else{ + // log.debug("Scheduler {} has not stoped normally and will be shut down + // immediately", + // scheduler.getThreadNamePrefix()); + // scheduler.getScheduledExecutor().shutdownNow(); + // log.info("Scheduler {} has shut down immediately", + // scheduler.getThreadNamePrefix()); + // + // } + // + // } catch (final IllegalStateException e) { + // e.printStackTrace(); + // + // } catch (final InterruptedException e) { + // e.printStackTrace(); + // + // } finally { + // scheduler.shutdown(); + // + // } + // } + + } + + private void internalIDestroyableObject(final Map objectsToDestroy) { + if (objectsToDestroy != null) { + final Iterator> interator = + objectsToDestroy.entrySet().iterator(); + while (interator.hasNext()) { + final Entry object = interator.next(); + try { + object.getValue().fullyDestroy(); + log.debug("Object with ID: {} is destroyed", object.getKey()); + + } catch (final Exception e) { + log.warn("Destroing object with ID: {} FAILED!", object.getKey(), null, e); + + } + } + } + + } + +} diff --git a/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 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 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/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..2cb0c83a --- /dev/null +++ b/connector/src/main/resources/application.properties @@ -0,0 +1,144 @@ +## 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 + + +##Monitoring +eidas.ms.monitoring.eIDASNode.metadata.url= + + +##Specific logger configuration +eidas.ms.technicallog.write.MDS.into.techlog=true +eidas.ms.revisionlog.write.MDS.into.revisionlog=true +eidas.ms.revisionlog.logIPAddressOfUser=true + + +##Directory for static Web content +eidas.ms.webcontent.static.directory=webcontent/ +eidas.ms.webcontent.templates=templates/ +eidas.ms.webcontent.properties=properties/messages +eidas.ms.webcontent.templates.countryselection=countrySelection.html + + +## extended validation of pending-request Id's +eidas.ms.core.pendingrequestid.maxlifetime=300 +eidas.ms.core.pendingrequestid.digist.algorithm=HmacSHA256 +#eidas.ms.core.pendingrequestid.digist.secret=pendingReqIdSecret + + +## eIDAS Ref. Implementation connector ### +eidas.ms.auth.eIDAS.node_v2.entityId=ownSpecificConnector +#eidas.ms.auth.eIDAS.node_v2.forward.endpoint= +eidas.ms.auth.eIDAS.node_v2.forward.method=POST +eidas.ms.auth.eIDAS.node_v2.countrycode=AT +eidas.ms.auth.eIDAS.node_v2.publicSectorTargets=.* +eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true +eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true + +eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/substantial + +#eidas.ms.auth.eIDAS.szrclient.useTestService=true +#eidas.ms.auth.eIDAS.szrclient.endpoint.prod= +#eidas.ms.auth.eIDAS.szrclient.endpoint.test=http://localhost:1234/demoszr +#eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.path=keys/junit.jks +#eidas.ms.auth.eIDAS.szrclient.ssl.keyStore.password=password +#eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.path= +#eidas.ms.auth.eIDAS.szrclient.ssl.trustStore.password= +eidas.ms.auth.eIDAS.szrclient.timeout.connection=15 +eidas.ms.auth.eIDAS.szrclient.timeout.response=30 +eidas.ms.auth.eIDAS.szrclient.params.vkz= + +eidas.ms.auth.eIDAS.szrclient.params.useSZRForbPKCalculation=false + + +# 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..8a21e68f 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"> - + + + @@ -27,13 +31,24 @@ + + + + - + + + + + + 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 @@ - ${catalina.base}/logs/eidas-ms-reversion.log + logs/eidas-ms-specific.log %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n 9999 - ${catalina.base}/logs/eidas-ms-reversion.log.%i + logs/eidas-ms-specific.log.%i - ${catalina.base}/logs/eIDAS_node.log + logs/eIDAS_node.log %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n 9999 - ${catalina.base}/logs/eIDAS_node.log.%i + logs/eIDAS_node.log.%i - ${catalina.base}/logs/eidas-ms-reversion.log + logs/eidas-ms-reversion.log %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n 9999 - ${catalina.base}/logs/eidas-ms-reversion.log.%i + logs/eidas-ms-reversion.log.%i - ${catalina.base}/logs/eidas-ms-statistic.log + logs/eidas-ms-statistic.log %m%n 9999 - ${catalina.base}/logs/eidas-ms-statistic.log.%i + logs/eidas-ms-statistic.log.%i - ${catalina.base}/logs/console.log + logs/console.log %5p | %d{dd HH:mm:ss,SSS} | %t | %m%n 9999 - ${catalina.base}/logs/console.log.%i + logs/console.log.%i - - - + - - @@ -43,7 +41,7 @@ - @@ -96,17 +94,6 @@ - - - - - - - - - - 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 -- cgit v1.2.3 From f06839fb716ff61bf94a32f8e23e3f313245f7e7 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Sat, 26 Dec 2020 17:45:38 +0100 Subject: add jUnit test that simulates a full eIDAS authentication --- ...MsSpecificSpringBootApplicationContextInitializer.java | 2 +- .../connector/SpringBootApplicationInitializer.java | 15 ++++++++++++++- .../connector/provider/StatusMessageProvider.java | 4 ++-- connector/src/main/resources/application.properties | 4 +++- 4 files changed, 20 insertions(+), 5 deletions(-) (limited to 'connector/src/main') 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 index 5160bdf5..399d1286 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/MsSpecificSpringBootApplicationContextInitializer.java @@ -41,7 +41,7 @@ public class MsSpecificSpringBootApplicationContextInitializer extends } super.initialize(applicationContext); - + } private void injectConfiguration(String configPath, ConfigurableApplicationContext applicationContext) { 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 index 0d3226bf..f0cf8698 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java @@ -4,8 +4,11 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; +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.core.impl.utils.Random; +import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xInitializer; import lombok.extern.slf4j.Slf4j; @Slf4j @@ -18,8 +21,9 @@ public class SpringBootApplicationInitializer { * 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) { + public static void main(final String[] args) throws Throwable { try { log.info("=============== Initializing Spring-Boot context! ==============="); LogMessageProviderFactory.setStatusMessager(new SimpleStatusMessager()); @@ -27,9 +31,18 @@ public class SpringBootApplicationInitializer { 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("Seed random number generator ... "); + Random.seedRandom(); + log.info("Initialization of MS-specific eIDAS-Implementation finished."); } catch (final Throwable 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/resources/application.properties b/connector/src/main/resources/application.properties index 2cb0c83a..68e07714 100644 --- a/connector/src/main/resources/application.properties +++ b/connector/src/main/resources/application.properties @@ -13,13 +13,15 @@ app.build.artifactId=ms_connector 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= -- cgit v1.2.3 From 063e6279147b1c532a8e8afae7209756b7f8b175 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Sat, 26 Dec 2020 19:16:41 +0100 Subject: switch to SpringBoot as default --- .../connector/SpringContextCloseHandler.java | 56 +------ .../specific/connector/SpringInitializer.java | 186 --------------------- .../src/main/resources/applicationContext.xml | 4 +- 3 files changed, 3 insertions(+), 243 deletions(-) delete mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/SpringInitializer.java (limited to 'connector/src/main') 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 index 2a3b659a..e884b5c6 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringContextCloseHandler.java @@ -133,29 +133,6 @@ public class SpringContextCloseHandler private void internalThreadPoolTaskExecutor(final Map executers) { for (final ThreadPoolTaskExecutor executor : executers.values()) { - // Not needed yet - // int retryCount = 0; - // while(executor.getActiveCount()>0 && ++retryCount<51){ - // try { - // log.debug("Executer {} is still working with active {} work. Retry count is - // {}", - // executor.getThreadNamePrefix(), - // executor.getActiveCount(), - // retryCount); - // Thread.sleep(1000); - // - // } catch (final InterruptedException e) { - // e.printStackTrace(); - // } - // } - // - // if(!(retryCount<51)) - // log.debug("Executer {} is still working. Since Retry count exceeded max value - // {}, will be - // killed immediately", - // executor.getThreadNamePrefix(), - // retryCount); - executor.shutdown(); log.debug("Executer {} with active {} work has killed", executor.getThreadNamePrefix(), executor.getActiveCount()); @@ -168,38 +145,7 @@ public class SpringContextCloseHandler private void internalThreadPoolTaskScheduler( final Map schedulers) { log.trace("Stopping #{} task-schedulers", schedulers.size()); - - // for (final ThreadPoolTaskScheduler scheduler : schedulers.values()) { - // scheduler.getScheduledExecutor().shutdown(); - // try { - // scheduler.getScheduledExecutor().awaitTermination(20000, - // TimeUnit.MILLISECONDS); - // if(scheduler.getScheduledExecutor().isTerminated() || - // scheduler.getScheduledExecutor().isShutdown()) - // log.debug("Scheduler {} has stoped", scheduler.getThreadNamePrefix()); - // - // else{ - // log.debug("Scheduler {} has not stoped normally and will be shut down - // immediately", - // scheduler.getThreadNamePrefix()); - // scheduler.getScheduledExecutor().shutdownNow(); - // log.info("Scheduler {} has shut down immediately", - // scheduler.getThreadNamePrefix()); - // - // } - // - // } catch (final IllegalStateException e) { - // e.printStackTrace(); - // - // } catch (final InterruptedException e) { - // e.printStackTrace(); - // - // } finally { - // scheduler.shutdown(); - // - // } - // } - + } private void internalIDestroyableObject(final Map objectsToDestroy) { 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/resources/applicationContext.xml b/connector/src/main/resources/applicationContext.xml index 8a21e68f..15ce0a55 100644 --- a/connector/src/main/resources/applicationContext.xml +++ b/connector/src/main/resources/applicationContext.xml @@ -39,13 +39,13 @@ location="${eidas.ms.configuration}" /> --> - + - + -- cgit v1.2.3 From 85c0c06c4ccd513a32f9f562deeba4038dcb95f4 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Sat, 26 Dec 2020 19:17:15 +0100 Subject: update default-configuration and example configuration --- connector/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'connector/src/main') diff --git a/connector/src/main/resources/application.properties b/connector/src/main/resources/application.properties index 68e07714..ef83d435 100644 --- a/connector/src/main/resources/application.properties +++ b/connector/src/main/resources/application.properties @@ -56,7 +56,7 @@ eidas.ms.auth.eIDAS.node_v2.workarounds.addAlwaysProviderName=true eidas.ms.auth.eIDAS.node_v2.workarounds.useRequestIdAsTransactionIdentifier=true eidas.ms.auth.eIDAS.node_v2.workarounds.useStaticProviderNameForPublicSPs=true -eidas.ms.auth.eIDAS.node_v2.loa.requested.minimum=http://eidas.europa.eu/LoA/substantial +eidas.ms.auth.eIDAS.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= -- cgit v1.2.3 From d9c6a5c8bf3cab0311fc25b38b308b22ec852a3e Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Mon, 28 Dec 2020 16:34:05 +0100 Subject: update SpringBoot application-initializer to enable package-scanning in application packages --- .../eidas/specific/connector/SpringBootApplicationInitializer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'connector/src/main') 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 index f0cf8698..1e84cbb0 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/SpringBootApplicationInitializer.java @@ -12,7 +12,10 @@ import at.gv.egiz.eaaf.modules.pvp2.impl.opensaml.initialize.EaafOpenSaml3xIniti import lombok.extern.slf4j.Slf4j; @Slf4j -@SpringBootApplication(scanBasePackages = {"at.gv.egiz.eaaf.utils.springboot.ajp"}) +@SpringBootApplication(scanBasePackages = { + "at.asitplus.eidas.specific.connector", + "at.gv.egiz.eaaf.utils.springboot.ajp" + }) public class SpringBootApplicationInitializer { private static ConfigurableApplicationContext ctx; -- cgit v1.2.3 From 278c8a6d1f0518dc9d0875dbec84614b19800d5d Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 7 Jan 2021 20:03:54 +0100 Subject: switch from custom monitoring to Spring-Actuator healthchecks --- .../connector/controller/MonitoringController.java | 279 --------------------- .../health/EidasNodeMetadataHealthIndicator.java | 69 +++++ .../health/Saml2MetadataHealthIndicator.java | 44 ++++ .../tasks/GenerateCountrySelectionFrameTask.java | 11 +- .../EidasCacheTransactionStoreDecorator.java | 32 ++- .../main/resources/SpringTest_connector.beans.xml | 129 ---------- .../resources/specific_eIDAS_connector.beans.xml | 7 +- 7 files changed, 149 insertions(+), 422 deletions(-) delete mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java delete mode 100644 connector/src/main/resources/SpringTest_connector.beans.xml (limited to 'connector/src/main') diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java deleted file mode 100644 index f2d9fc8c..00000000 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/controller/MonitoringController.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2018 A-SIT Plus GmbH - * AT-specific eIDAS Connector has been developed in a cooperation between EGIZ, - * A-SIT Plus GmbH, A-SIT, and Graz University of Technology. - * - * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "License"); - * You may not use this work except in compliance with the License. - * You may obtain a copy of the License at: - * https://joinup.ec.europa.eu/news/understanding-eupl-v12 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This product combines work with different licenses. See the "NOTICE" text - * file for details on the various modules and licenses. - * The "NOTICE" text file is part of the distribution. Any derivative works - * that you distribute must include a readable copy of the "NOTICE" text file. -*/ - -package at.asitplus.eidas.specific.connector.controller; - -import java.io.IOException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.transform.TransformerFactoryConfigurationError; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.text.StringEscapeUtils; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.utils.URIBuilder; -import org.apache.http.impl.client.CloseableHttpClient; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; -import at.gv.egiz.eaaf.core.api.data.EaafConstants; -import at.gv.egiz.eaaf.core.api.idp.IConfigurationWithSP; -import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; -import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; -import at.gv.egiz.eaaf.core.impl.utils.DomUtils; -import at.gv.egiz.eaaf.core.impl.utils.Random; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; -import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; -import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; -import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; - -@Controller -public class MonitoringController { - private static final Logger log = LoggerFactory.getLogger(MonitoringController.class); - - private static final String MESSAGE_OK = "OK"; - private static final String MESSAGE_ERROR = "ERROR"; - private static final String MESSAGE_SKIPPED = "SKIPPED"; - - private static final String TEST_STORAGE = "Storage: "; - private static final String TEST_CONFIG = "Config: "; - private static final String TEST_PVPMETADATA = "PVP_metadata: "; - private static final String TEST_EIDASNODEMETADATA = "eIDASNode_metadata: "; - - @Autowired - private ITransactionStorage storage; - @Autowired - private IConfigurationWithSP config; - - @Autowired private IHttpClientFactory httpClientFactory; - - @Autowired - private PvpMetadataBuilder metadatabuilder; - @Autowired - private IPvpMetadataConfigurationFactory configFactory; - private AbstractCredentialProvider pvpIdpCredentials; - - /** - * Sets a specific credential provider for PVP S-Profile IDP component. - * - * @param pvpIdpCredentials credential provider - */ - public void setPvpIdpCredentials(AbstractCredentialProvider pvpIdpCredentials) { - this.pvpIdpCredentials = pvpIdpCredentials; - - } - - /** - * Generic exception handling that wrote an error-message to html response. - * - * @param resp Http response object - * @param exception Error - * @throws IOException In case of a html response error. - */ - @ExceptionHandler({ Throwable.class }) - public void genericExceptionHandler(HttpServletResponse resp, Exception exception) throws IOException { - log.error("Monitoring Servlet receives an error.", exception); - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write("Reason: " - + StringEscapeUtils.escapeHtml4(StringEscapeUtils.escapeEcmaScript(exception.getMessage()))); - - } - - /** - * MS-Connector status-monitoring end-point. - * - * @param req http request - * @param resp http response - * @throws IOException In case of a general processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_MONITOR }, - method = { RequestMethod.GET }) - public void startFullTest(HttpServletRequest req, HttpServletResponse resp) throws IOException { - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - - try { - testConfig(); - testStorage(); - testPvpMetadata(); - testEidasNodeMetadata(); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(MESSAGE_OK); - - } catch (final Exception e) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - resp.getWriter().write(MESSAGE_ERROR); - - } - - } - - /** - * MS-Connector internal verify monitoring end-point. - * - * @param req http request object - * @param resp http response object - * @throws IOException In case of an internal processing error - */ - @RequestMapping(value = { MsEidasNodeConstants.ENDPOINT_MONITORING_VERIFY }, - method = { RequestMethod.GET }) - - public void startSingleTests(HttpServletRequest req, HttpServletResponse resp) throws IOException { - String result = StringUtils.EMPTY; - try { - result += testConfig() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testStorage() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testPvpMetadata() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - try { - result += testEidasNodeMetadata() + "
"; - } catch (final Exception e) { - result += e.getMessage() + "
"; - } - - resp.setContentType(EaafConstants.CONTENTTYPE_HTML_UTF8); - resp.setStatus(HttpServletResponse.SC_OK); - resp.getWriter().write(result); - - } - - private String testStorage() throws Exception { - try { - final String key = Random.nextHexRandom16(); - final String value = Random.nextHexRandom16(); - - storage.put(key, value, -1); - final String result = storage.get(key, String.class); - storage.remove(key); - - if (result != null && result.equals(value)) { - return TEST_STORAGE + MESSAGE_OK; - } else { - log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); - } - - } catch (final EaafException e) { - log.warn("Montioring: Can not read/write to storage.", e); - - } - - throw new Exception(TEST_STORAGE + MESSAGE_ERROR); - - } - - private String testConfig() throws Exception { - try { - if (config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) != null - && config.getBasicConfigurationWithPrefix(MsEidasNodeConstants.PROP_CONFIG_SP_LIST_PREFIX) - .size() > 0) { - return TEST_CONFIG + MESSAGE_OK; - } else { - log.warn("Montioring: Can not read from configuration file."); - } - - } catch (final Exception e) { - log.warn("Montioring: Can not read from configuration file.", e); - } - - throw new Exception(TEST_CONFIG + MESSAGE_ERROR); - - } - - private String testPvpMetadata() throws Exception { - try { - // build metadata - final IPvpMetadataBuilderConfiguration metadataConfig = - configFactory.generateMetadataBuilderConfiguration( - "http://localhost/monitoring", - pvpIdpCredentials); - metadatabuilder.buildPvpMetadata(metadataConfig); - return TEST_PVPMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_PVPMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_PVPMETADATA + MESSAGE_ERROR, e); - - } - - } - - private String testEidasNodeMetadata() throws Exception { - try { - final String urlString = config.getBasicConfiguration( - MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); - if (StringUtils.isEmpty(urlString)) { - log.debug("No eIDASNode metadata URL. Skipping test ... "); - return TEST_EIDASNODEMETADATA + MESSAGE_SKIPPED; - - } - - // create HTTP client - CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); - URIBuilder uriBuilder = new URIBuilder(urlString); - HttpUriRequest request = new HttpGet(uriBuilder.build()); - - final CloseableHttpResponse respCode = httpClient.execute(request); - if (respCode.getStatusLine().getStatusCode() != 200) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + " HTTP responsecode: " - + respCode); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR); - - } - - // parse metadata - DomUtils.parseXmlNonValidating(respCode.getEntity().getContent()); - - return TEST_EIDASNODEMETADATA + MESSAGE_OK; - - } catch (Exception | TransformerFactoryConfigurationError e) { - log.warn("Monitoring: Has an error in '" + TEST_EIDASNODEMETADATA + "': " + e.getMessage(), e); - throw new Exception(TEST_EIDASNODEMETADATA + MESSAGE_ERROR, e); - - } - - } - -} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java new file mode 100644 index 00000000..f160916c --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/EidasNodeMetadataHealthIndicator.java @@ -0,0 +1,69 @@ +package at.asitplus.eidas.specific.connector.health; + +import java.io.ByteArrayInputStream; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.CloseableHttpClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.asitplus.eidas.specific.connector.MsEidasNodeConstants; +import at.gv.egiz.eaaf.core.api.idp.IConfiguration; +import at.gv.egiz.eaaf.core.impl.data.Triple; +import at.gv.egiz.eaaf.core.impl.http.HttpUtils; +import at.gv.egiz.eaaf.core.impl.http.IHttpClientFactory; +import at.gv.egiz.eaaf.core.impl.utils.DomUtils; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class EidasNodeMetadataHealthIndicator implements HealthIndicator { + + @Autowired IConfiguration config; + @Autowired IHttpClientFactory httpClientFactory; + + @Override + public Health health() { + try { + final String urlString = config.getBasicConfiguration( + MsEidasNodeConstants.PROP_CONFIG_MONITORING_EIDASNODE_METADATAURL); + if (StringUtils.isEmpty(urlString)) { + log.trace("No eIDASNode metadata URL. Skipping test ... "); + return Health.unknown().build(); + + } + + // create HTTP client + CloseableHttpClient httpClient = httpClientFactory.getHttpClient(); + URIBuilder uriBuilder = new URIBuilder(urlString); + HttpUriRequest request = new HttpGet(uriBuilder.build()); + + final Triple respCode = httpClient.execute(request, + HttpUtils.bodyStatusCodeResponseHandler()); + if (respCode.getFirst().getStatusCode() != 200) { + log.warn("Monitoring: Get http StatusCode: {} from eIDAS-Node Metadata endpoint", + respCode.getFirst().getStatusCode()); + return Health.down().withDetail("http StatusCode", respCode.getFirst().getStatusCode()).build(); + + } + + // parse metadata + DomUtils.parseXmlNonValidating(respCode.getSecond()); + + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + log.warn("Monitoring: Can not read SAML2 metadata from eIDAS-Node", e); + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java new file mode 100644 index 00000000..592231b0 --- /dev/null +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/health/Saml2MetadataHealthIndicator.java @@ -0,0 +1,44 @@ +package at.asitplus.eidas.specific.connector.health; + +import javax.xml.transform.TransformerFactoryConfigurationError; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; + +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataBuilderConfiguration; +import at.gv.egiz.eaaf.modules.pvp2.api.metadata.IPvpMetadataConfigurationFactory; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpMetadataBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.AbstractCredentialProvider; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class Saml2MetadataHealthIndicator implements HealthIndicator { + + @Autowired + private PvpMetadataBuilder metadatabuilder; + @Autowired + private IPvpMetadataConfigurationFactory configFactory; + + @Setter + private AbstractCredentialProvider pvpIdpCredentials; + + @Override + public Health health() { + try { + // build metadata + final IPvpMetadataBuilderConfiguration metadataConfig = + configFactory.generateMetadataBuilderConfiguration( + "http://localhost/monitoring", + pvpIdpCredentials); + metadatabuilder.buildPvpMetadata(metadataConfig); + return Health.up().build(); + + } catch (Exception | TransformerFactoryConfigurationError e) { + return Health.down().down(e).build(); + + } + } + +} diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java index 86808f01..d3b8116a 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/processes/tasks/GenerateCountrySelectionFrameTask.java @@ -26,8 +26,6 @@ package at.asitplus.eidas.specific.connector.processes.tasks; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -39,7 +37,6 @@ import at.gv.egiz.eaaf.core.api.gui.ISpringMvcGuiFormBuilder; import at.gv.egiz.eaaf.core.api.idp.IConfiguration; import at.gv.egiz.eaaf.core.api.idp.process.ExecutionContext; import at.gv.egiz.eaaf.core.exceptions.EaafException; -import at.gv.egiz.eaaf.core.exceptions.GuiBuildException; import at.gv.egiz.eaaf.core.exceptions.TaskExecutionException; import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; @@ -51,7 +48,6 @@ import at.gv.egiz.eaaf.core.impl.idp.auth.modules.AbstractAuthServletTask; */ @Component("GenerateCountrySelectionFrameTask") public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { - private static final Logger log = LoggerFactory.getLogger(GenerateCountrySelectionFrameTask.class); @Autowired ISpringMvcGuiFormBuilder guiBuilder; @@ -77,16 +73,11 @@ public class GenerateCountrySelectionFrameTask extends AbstractAuthServletTask { guiBuilder.build(request, response, config, "BKU-Selection form"); - } catch (final GuiBuildException e) { - log.warn("Can not build GUI:'BKU-Selection'. Msg:" + e.getMessage()); + } catch (final Exception e) { throw new TaskExecutionException(pendingReq, "Can not build GUI. Msg:" + e.getMessage(), new EaafException("gui.00", new Object[] { e.getMessage() }, e)); - } catch (final Exception e) { - log.warn("FinalizeAuthenticationTask has an internal error", e); - throw new TaskExecutionException(pendingReq, e.getMessage(), e); - } } diff --git a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java index 557e245a..1ea5a280 100644 --- a/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java +++ b/connector/src/main/java/at/asitplus/eidas/specific/connector/storage/EidasCacheTransactionStoreDecorator.java @@ -30,17 +30,46 @@ import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthIndicator; import at.gv.egiz.eaaf.core.api.storage.ITransactionStorage; import at.gv.egiz.eaaf.core.exceptions.EaafException; import at.gv.egiz.eaaf.core.exceptions.EaafStorageException; +import at.gv.egiz.eaaf.core.impl.utils.Random; -public class EidasCacheTransactionStoreDecorator implements ITransactionStorage { +public class EidasCacheTransactionStoreDecorator implements ITransactionStorage, HealthIndicator { private static final Logger log = LoggerFactory.getLogger(EidasCacheTransactionStoreDecorator.class); @Autowired(required = true) private CacheWithEidasBackend storage; + @Override + public Health health() { + try { + final String key = Random.nextHexRandom16(); + final String value = Random.nextHexRandom16(); + + this.put(key, value, -1); + final String result = this.get(key, String.class); + this.remove(key); + + if (result != null && result.equals(value)) { + return Health.up().build(); + + } else { + log.warn("Montioring: TestValue: " + value + " does NOT match in Storage test"); + return Health.down().build(); + + } + + } catch (final EaafException e) { + log.warn("Montioring: Can not read/write to storage.", e); + return Health.down().down(e).build(); + + } + } + @Override public void changeKey(String oldKey, String newKey, Object value) throws EaafException { if (containsKey(oldKey)) { @@ -148,5 +177,4 @@ public class EidasCacheTransactionStoreDecorator implements ITransactionStorage } } - } diff --git a/connector/src/main/resources/SpringTest_connector.beans.xml b/connector/src/main/resources/SpringTest_connector.beans.xml deleted file mode 100644 index 5cf0d5b8..00000000 --- a/connector/src/main/resources/SpringTest_connector.beans.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/connector/src/main/resources/specific_eIDAS_connector.beans.xml b/connector/src/main/resources/specific_eIDAS_connector.beans.xml index aa5040fa..f6fdeefe 100644 --- a/connector/src/main/resources/specific_eIDAS_connector.beans.xml +++ b/connector/src/main/resources/specific_eIDAS_connector.beans.xml @@ -19,13 +19,16 @@ - + + + -- cgit v1.2.3 From 8d8221ab72222bae0fe50bfd1e8b4266eec40e11 Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Sat, 9 Jan 2021 18:55:15 +0100 Subject: add HealthIndicator to check Apache-Ignite cluster-state --- .../health/IgniteClusterHealthIndicator.java | 52 ++++++++++++++++++++++ .../specific_eIDAS_connector.storage.beans.xml | 9 ++-- 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 connector/src/main/java/at/asitplus/eidas/specific/connector/health/IgniteClusterHealthIndicator.java (limited to 'connector/src/main') 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/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 @@ - + + + + +