diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index f8eb32a38..ec11c9e43 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -128,11 +128,6 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { //TODO: We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type) if ((mr.type != 'BaseMetadataResolver') && (mr.enabled)) { constructXmlNodeForResolver(mr, delegate) { - MetadataFilter( - 'xsi:type': 'SignatureValidation', - 'requireSignedRoot': 'true', - 'certificateFile': '%{idp.home}/credentials/inc-md-cert.pem' - ) //TODO: enhance mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter -> constructXmlNodeForFilter(filter, delegate) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java index 3cb37ee1b..a63c3da6e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolversPositionOrderContainerRepository; import edu.internet2.tier.shibboleth.admin.ui.scheduled.EntityDescriptorFilesScheduledTasks; +import edu.internet2.tier.shibboleth.admin.ui.scheduled.MetadataProvidersScheduledTasks; import edu.internet2.tier.shibboleth.admin.ui.service.DefaultMetadataResolversPositionOrderContainerService; import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryService; import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryServiceImpl; @@ -34,6 +35,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; +import org.springframework.core.io.Resource; import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; @@ -95,6 +97,12 @@ public EntityDescriptorFilesScheduledTasks entityDescriptorFilesScheduledTasks(E return new EntityDescriptorFilesScheduledTasks(metadataDir, entityDescriptorRepository, openSamlObjects()); } + @Bean + @ConditionalOnProperty(name = "shibui.metadataProviders.target") + public MetadataProvidersScheduledTasks metadataProvidersScheduledTasks(@Value("${shibui.metadataProviders.target}") final Resource resource, final MetadataResolverService metadataResolverService) { + return new MetadataProvidersScheduledTasks(resource, metadataResolverService); + } + @Bean public EntityIdsSearchService entityIdsSearchService(LuceneUtility luceneUtility, Analyzer fullTokenAnalyzer) { return new EntityIdsSearchServiceImpl(luceneUtility, fullTokenAnalyzer); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/MetadataProvidersScheduledTasks.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/MetadataProvidersScheduledTasks.java new file mode 100644 index 000000000..49048f39b --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/MetadataProvidersScheduledTasks.java @@ -0,0 +1,49 @@ +package edu.internet2.tier.shibboleth.admin.ui.scheduled; + +import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.transaction.annotation.Transactional; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.OutputStream; + +@Configuration +@ConditionalOnProperty("shibui.metadataProviders.target") +public class MetadataProvidersScheduledTasks { + private static final Logger logger = LoggerFactory.getLogger(MetadataProvidersScheduledTasks.class); + + private final Resource target; + private final MetadataResolverService metadataResolverService; + + public MetadataProvidersScheduledTasks(Resource target, MetadataResolverService metadataResolverService) { + this.target = target; + this.metadataResolverService = metadataResolverService; + } + + @Scheduled(fixedRateString = "${shibui.metadataProviders.taskRunRate:30000}") + @Transactional(readOnly = true) + public void generateMetadataProvidersFile() { + try (OutputStream os = ((WritableResource)target).getOutputStream()) { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + + transformer.transform(new DOMSource(metadataResolverService.generateConfiguration()), new StreamResult(os)); + } catch (IOException | TransformerException e) { + logger.error(e.getLocalizedMessage(), e); + } + } +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 634d32c5b..7b290d0d4 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -52,3 +52,9 @@ spring.profiles.active=default #Actuator endpoints (info) # Un-comment to get full git details exposed like author, abbreviated SHA-1, commit message #management.info.git.mode=full + +### +# metadata-providers.xml write configuration + +# shibui.metadataProviders.target=file:/opt/shibboleth-idp/conf/shibui-metadata-providers.xml +# shibui.metadataProviders.taskRunRate=30000 diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy index 279f4a6ba..003e8c167 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/IncommonJPAMetadataResolverServiceImplTests.groovy @@ -7,6 +7,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFil import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityRoleWhiteListFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.SignatureValidationFilter import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator @@ -48,6 +49,7 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { def 'simple test generation of metadata-providers.xml'() { when: def mr = metadataResolverRepository.findAll().iterator().next() + mr.metadataFilters << new SignatureValidationFilter(requireSignedRoot: true, certificateFile: '%{idp.home}/credentials/inc-md-cert.pem') mr.metadataFilters << requiredValidUntilFilterForXmlGenerationTests() mr.metadataFilters << entityRoleWhiteListFilterForXmlGenerationTests() metadataResolverRepository.save(mr) @@ -63,6 +65,7 @@ class IncommonJPAMetadataResolverServiceImplTests extends Specification { when: //TODO: this might break later def mr = metadataResolverRepository.findAll().iterator().next() + mr.metadataFilters << new SignatureValidationFilter(requireSignedRoot: true, certificateFile: '%{idp.home}/credentials/inc-md-cert.pem') mr.metadataFilters << requiredValidUntilFilterForXmlGenerationTests() mr.metadataFilters.add(new EntityAttributesFilter().with { it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml index 34bf7ae16..20b513e1f 100644 --- a/backend/src/test/resources/conf/278.2.xml +++ b/backend/src/test/resources/conf/278.2.xml @@ -23,7 +23,7 @@ socketTimeout="PT5S" supportedContentTypes="[]" xsi:type="DynamicHttpMetadataProvider"> - + - - - \ No newline at end of file diff --git a/backend/src/test/resources/conf/278.xml b/backend/src/test/resources/conf/278.xml index e47fbd838..3bebc347b 100644 --- a/backend/src/test/resources/conf/278.xml +++ b/backend/src/test/resources/conf/278.xml @@ -23,7 +23,7 @@ socketTimeout="PT5S" supportedContentTypes="[]" xsi:type="DynamicHttpMetadataProvider"> - + md:SPSSODescriptor @@ -35,8 +35,6 @@ metadataURL="https://idp.unicon.net/idp/shibboleth" minRefreshDelay='PT0M' maxRefreshDelay='P1D'> - - - \ No newline at end of file