Skip to content

Commit

Permalink
SHIBUI-2269
Browse files Browse the repository at this point in the history
Added ExternalMetadataResolver to resolver types.
TODO: define XML wrapper around filters block
TODO: Unit test
  • Loading branch information
chasegawa committed Jun 24, 2022
1 parent cc4a9f1 commit b7e9253
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -449,11 +449,11 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd'
) {


resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each {
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr ->
//TODO: We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type)
if ((mr.type != 'BaseMetadataResolver') && (mr.enabled)) {
// We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type)
// We do not want to include the custom type: ExternalMetadataResolver
if ((mr.type != 'BaseMetadataResolver') && (mr.type != 'ExternalMetadataResolver') && (mr.enabled)) {
constructXmlNodeForResolver(mr, delegate) {
//TODO: enhance
def didNamespaceProtectionFilter = !(shibUIConfiguration.protectedAttributeNamespaces && shibUIConfiguration.protectedAttributeNamespaces.size() > 0)
Expand All @@ -478,6 +478,44 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
}
}

@Override
Document generateExternalMetadataFilterConfiguration() {
// TODO: this can probably be a better writer
new StringWriter().withCloseable { writer ->
def xml = new MarkupBuilder(writer)
xml.omitEmptyAttributes = true
xml.omitNullAttributes = true

// CHARLESTODO - determine wrapping type here - possible: https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter
xml.MetadataProvider(id: 'ShibbolethIdPUIGeneratedMetadata',
xmlns: 'urn:mace:shibboleth:2.0:metadata',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:type': 'ChainingMetadataProvider',
'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd'
) {

resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each {
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr ->
// Only include the custom type: ExternalMetadataResolver
if ((mr.type != 'ExternalMetadataResolver') && (mr.enabled)) {
constructXmlNodeForResolver(mr, delegate) {
//TODO: enhance
def didNamespaceProtectionFilter = !(shibUIConfiguration.protectedAttributeNamespaces && shibUIConfiguration.protectedAttributeNamespaces.size() > 0)
mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter ->
if (filter.isFilterEnabled()) {
doNamespaceProtectionFilter()
constructXmlNodeForFilter(filter, delegate)
}
}
doNamespaceProtectionFilter()
}
}
}
}
return DOMBuilder.newInstance().parseText(writer.toString())
}
}

private String generateJavaScriptRegexScript(String regex) {
return """
"use strict";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.ExternalMetadataProvidersScheduledTasks;
import edu.internet2.tier.shibboleth.admin.ui.scheduled.MetadataProvidersScheduledTasks;
import edu.internet2.tier.shibboleth.admin.ui.security.model.listener.GroupUpdatedEntityListener;
import edu.internet2.tier.shibboleth.admin.ui.security.model.listener.UserUpdatedEntityListener;
Expand Down Expand Up @@ -88,6 +89,14 @@ public MetadataProvidersScheduledTasks metadataProvidersScheduledTasks(
return new MetadataProvidersScheduledTasks(resource, metadataResolverService, fileWritingService());
}

@Bean
@ConditionalOnProperty(name = "shibui.external.metadataProviders.target")
public ExternalMetadataProvidersScheduledTasks externalMetadataProvidersScheduledTasks(
@Value("${shibui.external.metadataProviders.target}") final Resource resource,
final MetadataResolverService metadataResolverService) {
return new ExternalMetadataProvidersScheduledTasks(resource, metadataResolverService, fileWritingService());
}

@Bean
public EntityIdsSearchService entityIdsSearchService(LuceneUtility luceneUtility, Analyzer fullTokenAnalyzer) {
return new EntityIdsSearchServiceImpl(luceneUtility, fullTokenAnalyzer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,20 @@ public ResponseEntity<?> getXml() throws IOException, TransformerException {
}
}

@GetMapping(value = "/MetadataResolvers/External", produces = "application/xml")
@Transactional(readOnly = true)
public ResponseEntity<?> getExternalXml() throws IOException, TransformerException {
// TODO: externalize
try (StringWriter writer = new StringWriter()) {
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.generateExternalMetadataFilterConfiguration()), new StreamResult(writer));
return ResponseEntity.ok(writer.toString());
}
}

@GetMapping("/MetadataResolvers/{resourceId}")
@Transactional(readOnly = true)
public ResponseEntity<?> getOne(@PathVariable String resourceId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers;

public class ExternalMetadataResolver extends MetadataResolver {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package edu.internet2.tier.shibboleth.admin.ui.scheduled;

import edu.internet2.tier.shibboleth.admin.ui.service.FileWritingService;
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.StringWriter;

@Configuration
@ConditionalOnProperty("shibui.external.metadataProviders.target")
public class ExternalMetadataProvidersScheduledTasks {
private static final Logger logger = LoggerFactory.getLogger(ExternalMetadataProvidersScheduledTasks.class);

private final Resource target;
private final MetadataResolverService metadataResolverService;
private final FileWritingService fileWritingService;

public ExternalMetadataProvidersScheduledTasks(Resource target, MetadataResolverService metadataResolverService, FileWritingService fileWritingService) {
this.target = target;
this.metadataResolverService = metadataResolverService;
this.fileWritingService = fileWritingService;
}

@Scheduled(fixedRateString = "${shibui.external.metadataProviders.taskRunRate:30000}")
@Transactional(readOnly = true)
public void generateMetadataProvidersFile() {
try (StringWriter os = new StringWriter()) {
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.generateExternalMetadataFilterConfiguration()), new StreamResult(os));
this.fileWritingService.write((WritableResource)this.target, os.toString());
} catch (IOException | TransformerException e) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException;
import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException;
import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException;
import org.w3c.dom.Node;

public interface MetadataResolverService {
public MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException;
Expand All @@ -16,4 +17,6 @@ public interface MetadataResolverService {
public void reloadFilters(String metadataResolverName);

public MetadataResolver updateMetadataResolverEnabledStatus(MetadataResolver existingResolver) throws ForbiddenException, MetadataFileNotFoundException, InitializationException;
}

public Document generateExternalMetadataFilterConfiguration();
}
6 changes: 6 additions & 0 deletions backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ shibui.nameid-filter-ui-schema-location=classpath:nameid-filter.schema.json
# shibui.metadataProviders.target=file:/opt/shibboleth-idp/conf/shibui-metadata-providers.xml
# shibui.metadataProviders.taskRunRate=30000

# Set the following property to periodically write out external metadata providers (ie metadata-filters) configuration.
# There is no default value; the following is just an example
# @see - https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter
# shibui.external.metadataProviders.target=file:/opt/shibboleth-idp/conf/metadata-filters.xml
# shibui.external.metadataProviders.taskRunRate=30000

# Email configuration (local mailhog)
# spring.mail.host=mailhog
# spring.mail.port=1025
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class MetadataFiltersControllerTests extends AbstractBaseDataJpaTest {
return null
}

@Override
Document generateExternalMetadataFilterConfiguration() {
return null
}

@Override
MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException {
// This won't get called
Expand Down

0 comments on commit b7e9253

Please sign in to comment.