From e984388c93de9820776642382b6ae4532836de9b Mon Sep 17 00:00:00 2001 From: Jj! Date: Wed, 22 Aug 2018 12:44:19 -0500 Subject: [PATCH 01/56] [NOISSUE] docker poc --- backend/Dockerfile | 9 +++++++++ backend/build.gradle | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 backend/Dockerfile diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 000000000..cec9c4c44 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,9 @@ +FROM gcr.io/distroless/java + +ARG JAR_FILE + +COPY ${JAR_FILE} app.jar + +EXPOSE 8080 + +CMD ["app.jar"] \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle index ca484d6cb..fc687b99d 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -5,6 +5,7 @@ plugins { id 'com.gorylenko.gradle-git-properties' version '1.4.21' id 'net.researchgate.release' version '2.6.0' id 'io.franzbecker.gradle-lombok' version '1.13' + id 'com.palantir.docker' version '0.20.1' } apply plugin: 'io.spring.dependency-management' @@ -206,4 +207,14 @@ jacocoTestReport { csv.enabled = false html.destination = file("${buildDir}/jacocoHtml") } +} + +tasks.docker.dependsOn tasks.build +docker { + name 'unicon/shibui' + tags 'latest' + pull true + noCache true + files tasks.bootWar.outputs + buildArgs(['JAR_FILE': 'shibui.war']) } \ No newline at end of file From 8cdbef594e717639653ee2a995a5fded05436f75 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Fri, 7 Sep 2018 13:14:59 -0700 Subject: [PATCH 02/56] [SHIBUI-570] Added simple caching of fetchMetdata and unmarshallMetadata. --- .../MetadataResolversController.java | 2 + ...penSamlFileBackedHTTPMetadataResolver.java | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index 4d7d7aaac..2b4b90d65 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -118,6 +118,8 @@ public ResponseEntity create(@RequestBody MetadataResolver newResolver) throw MetadataResolver persistedResolver = resolverRepository.save(newResolver); positionOrderContainerService.appendPositionOrderForNew(persistedResolver); + //TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets + // an valid response. This operation is not atomic. Should we return an error here? updateChainingMetadataResolver(persistedResolver); return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 5f4c10905..e74bff535 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -8,21 +8,35 @@ import org.apache.http.impl.client.HttpClients; import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; +import org.opensaml.core.xml.XMLObject; +import org.opensaml.core.xml.io.UnmarshallingException; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; +import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.InputStream; +import java.time.Instant; + import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; /** * @author Bill Smith (wsmith@unicon.net) */ public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver { + + private static final long MILLISECONDS_IN_ONE_SECOND = 1000; + private IndexWriter indexWriter; private FileBackedHttpMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; + private byte[] cachedMetadataBytes; + private Instant metadataLastFetchedAt; + boolean shouldRefreshMetadata; + XMLObject cachedMetadata; + public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, FileBackedHttpMetadataResolver sourceResolver) throws ResolverException { @@ -67,4 +81,31 @@ protected void initMetadataResolver() throws ComponentInitializationException { this.sourceResolver.getResourceId(), indexWriter); } + + @Override + protected byte[] fetchMetadata() throws ResolverException { + if (metadataLastFetchedAt == null || shouldRefreshMetadata()) { + this.cachedMetadataBytes = super.fetchMetadata(); + this.metadataLastFetchedAt = Instant.now(); + } + return cachedMetadataBytes; + } + + private boolean shouldRefreshMetadata() { + if ((Instant.now().getEpochSecond() - metadataLastFetchedAt.getEpochSecond()) > (this.getMinRefreshDelay() / MILLISECONDS_IN_ONE_SECOND)) { + shouldRefreshMetadata = true; + } + return shouldRefreshMetadata; + } + + @Override + protected XMLObject unmarshallMetadata(@Nonnull final InputStream metadataInput) + throws UnmarshallingException { + //TODO: This should probably be based on something other than minRefreshDelay + if (cachedMetadata == null || shouldRefreshMetadata) { + this.cachedMetadata = super.unmarshallMetadata(metadataInput); + this.shouldRefreshMetadata = false; + } + return this.cachedMetadata; + } } From 459df7185baa2bda1a299c421798081b2da51e82 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Fri, 7 Sep 2018 17:36:03 -0700 Subject: [PATCH 03/56] [SHIBUI-570] GRAMAAARRRRR --- .../admin/ui/controller/MetadataResolversController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index 2b4b90d65..7388679da 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -119,7 +119,7 @@ public ResponseEntity create(@RequestBody MetadataResolver newResolver) throw positionOrderContainerService.appendPositionOrderForNew(persistedResolver); //TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets - // an valid response. This operation is not atomic. Should we return an error here? + // n valid response. This operation is not atomic. Should we return an error here? updateChainingMetadataResolver(persistedResolver); return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver); From 75013d037ebad0a581bc22c1dd954db4b1ff164a Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Mon, 10 Sep 2018 16:56:33 -0700 Subject: [PATCH 04/56] [SHIBUI-570] Swapped MetadataResolverConverterServiceImpl's @Service annotation out for a new Configuration class with a new Bean declaration. How was this even working? Updated OpenSamlChainingMetadataResolver to initialize mutableResolvers with a new ArrayList instead of Collections.emptyList. Big mistake. Also, overrode resolve() to use the mutableResolvers list instead of the (empty) original resolvers list. Added new OpenSamlBatchMetadataResolverDelegate to handle refilter(). Added refilter() to all Batch-ish OpenSaml resolvers. Removed refreshOrInitResolver from filter controller. Not needed. Added refilter() calls in JPAMetadataResolverServiceImpl.reloadFilters. --- ...OpenSamlBatchMetadataResolverDelegate.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java new file mode 100644 index 000000000..855de838f --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java @@ -0,0 +1,19 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml; + +import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.metadata.resolver.impl.AbstractBatchMetadataResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +public class OpenSamlBatchMetadataResolverDelegate extends AbstractBatchMetadataResolver { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlBatchMetadataResolverDelegate.class); + + //TODO: Not sure this delegate is really buying us anything.. other than to get this one line in to a shared class. + //Maybe we'll do more in here later? + public void refilter(AbstractBatchMetadataResolver.BatchEntityBackingStore backingStore, XMLObject filteredMetadata) { + backingStore.setCachedFilteredMetadata(filteredMetadata); + } +} From 0cd425443fa51158ac2d11dd4da6be12fd5c5676 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 08:13:29 -0400 Subject: [PATCH 05/56] SHIBUI-836: work in progress --- .../admin/ui/ShibbolethUiApplication.java | 6 ++ ...eValueSettingEnvironmentPostProcessor.java | 57 +++++++++++++++++++ .../main/resources/META-INF/spring.factories | 2 + 3 files changed, 65 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java create mode 100644 backend/src/main/resources/META-INF/spring.factories diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index 1fc74cf9d..2c241cf8e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -2,6 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; @@ -36,10 +37,15 @@ public static class MetadataResolversResourceIdEmitter { @Autowired MetadataResolverRepository metadataResolverRepository; + @Value("${idp.home}") + String idpHome; + @EventListener void showMetadataResolversResourceIds(ApplicationStartedEvent e) { metadataResolverRepository.findAll() .forEach(it -> System.out.println(String.format("MetadataResolver [%s: %s]", it.getName(), it.getResourceId()))); + + System.out.println("IDP HOME: " + idpHome); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java new file mode 100644 index 000000000..74b35f362 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java @@ -0,0 +1,57 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration.postprocessors; + +import lombok.extern.log4j.Log4j2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +/** + * Spring Boot Environment Post Processor setting the value for idp.home property to an abstract temp directory. + * + * @author Dmitriy Kopylenko + */ +public class IdpHomeValueSettingEnvironmentPostProcessor implements EnvironmentPostProcessor { + + private static final String IDP_HOME_PROP = "idp.home"; + + private static final String METADATA_DIR = "metadata"; + + private static final Logger LOGGER = LoggerFactory.getLogger(IdpHomeValueSettingEnvironmentPostProcessor.class); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + String existingIdpHome = environment.getProperty(IDP_HOME_PROP); + Path metadataSubDir = Paths.get(existingIdpHome, METADATA_DIR); + if (existingIdpHome != null) { + if (!Files.exists(metadataSubDir)) { + try { + Files.createDirectories(metadataSubDir); + } catch (IOException e) { + LOGGER.error(e.getMessage()); + throw new RuntimeException(e); + } + } + return; + } + + Map map = new HashMap<>(1); + try { + map.put(IDP_HOME_PROP, Files.createTempDirectory(null).toAbsolutePath().toString()); + } catch (IOException e) { + LOGGER.error(e.getMessage()); + throw new RuntimeException(e); + } + environment.getPropertySources().addLast(new MapPropertySource("idp.home.propertysource", map)); + } +} diff --git a/backend/src/main/resources/META-INF/spring.factories b/backend/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000..fc0a891d0 --- /dev/null +++ b/backend/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.env.EnvironmentPostProcessor=\ + edu.internet2.tier.shibboleth.admin.ui.configuration.postprocessors.IdpHomeValueSettingEnvironmentPostProcessor \ No newline at end of file From 7c8ef09b8882ac095d129e430f441976da1400d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 10:20:31 -0400 Subject: [PATCH 06/56] SHIBUI-836: wip... property replacer API --- .../admin/ui/ShibbolethUiApplication.java | 12 ++++++++ ...eValueSettingEnvironmentPostProcessor.java | 9 ++++-- ...lverPropertyPlaceholderValuesReplacer.java | 17 +++++++++++ ...ertyPlaceholderValuesResolvingService.java | 29 +++++++++++++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index 2c241cf8e..db1779592 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -11,6 +11,8 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Profile; import org.springframework.context.event.EventListener; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.env.PropertyResolver; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Component; @@ -40,12 +42,22 @@ public static class MetadataResolversResourceIdEmitter { @Value("${idp.home}") String idpHome; + @Autowired + PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer; + + @Autowired + PropertyResolver propertyResolver; + @EventListener void showMetadataResolversResourceIds(ApplicationStartedEvent e) { metadataResolverRepository.findAll() .forEach(it -> System.out.println(String.format("MetadataResolver [%s: %s]", it.getName(), it.getResourceId()))); System.out.println("IDP HOME: " + idpHome); + String rawValue = "%{idp.home}/metadata/file.xml"; + boolean hasToken = rawValue.contains("%{idp.home}"); + String resolvedIdpHome = propertyResolver.resolvePlaceholders("${idp.home}"); + String fullyResolvedDir = rawValue.replace("%{idp.home}", resolvedIdpHome); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java index 74b35f362..814a797c2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java @@ -17,7 +17,8 @@ import java.util.Map; /** - * Spring Boot Environment Post Processor setting the value for idp.home property to an abstract temp directory. + * Spring Boot Environment Post Processor setting the value for idp.home property to an abstract temp directory + * if no IDP_HOME environment variable has been set already. * * @author Dmitriy Kopylenko */ @@ -47,7 +48,11 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp Map map = new HashMap<>(1); try { - map.put(IDP_HOME_PROP, Files.createTempDirectory(null).toAbsolutePath().toString()); + Path tempDir = Files.createTempDirectory(String.format("%s.%s.", "shibui", IDP_HOME_PROP)); + String tempDirName = tempDir.toAbsolutePath().toString(); + Path tempMetadataSubDir = Paths.get(tempDirName, METADATA_DIR); + Files.createDirectories(tempMetadataSubDir); + map.put(IDP_HOME_PROP, tempDirName); } catch (IOException e) { LOGGER.error(e.getMessage()); throw new RuntimeException(e); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java new file mode 100644 index 000000000..10887e97f --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java @@ -0,0 +1,17 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +/** + * An SPI to resolve and convert data for different types of {@link MetadataResolver}s from possible provided '%{}' placeholders + *

+ * Typical usage is - multiple replacers for concrete type of resolvers are configured in Spring Application Context, + * aggregated by {@link MetadataResolverPropertyPlaceholderValuesResolvingService} facade and then that facade is injected into upstream consumers of it + * such as REST controllers, etc. + * + * @author Dmitriy Kopylenko + */ +public interface MetadataResolverPropertyPlaceholderValuesReplacer { + + boolean supports(T metadataResolver); + + void replacePlaceholderValuesIfResolvableOrFail(T metadataResolver); +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java new file mode 100644 index 000000000..e7639cfde --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java @@ -0,0 +1,29 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import java.util.ArrayList; +import java.util.List; + +/** + * A facade that aggregates {@link MetadataResolverPropertyPlaceholderValuesReplacer}s available to call just one of them supporting the type of a given resolver. + * If no {@link MetadataResolverPropertyPlaceholderValuesReplacer}s are configured, considers a noop. + * + * Uses chain-of-responsibility design pattern + * + * @author Dmitriy Kopylenko + */ +public class MetadataResolverPropertyPlaceholderValuesResolvingService { + + private List> replacers; + + public MetadataResolverPropertyPlaceholderValuesResolvingService(List> replacers) { + this.replacers = replacers != null ? replacers : new ArrayList<>(); + } + + public void replacePlacehoderValuesOrFail(T metadataResolver) { + this.replacers + .stream() + .filter(r -> r.supports(metadataResolver)) + .findFirst() + .ifPresent(r -> r.replacePlaceholderValuesIfResolvableOrFail(metadataResolver)); + } +} From fdbe478994c9c411942d61fb12dce56970e85634 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 11 Sep 2018 08:11:16 -0700 Subject: [PATCH 07/56] [SHIBUI-570] Swapped MetadataResolverConverterServiceImpl's @Service annotation out for a new Configuration class with a new Bean declaration. How was this even working? Updated OpenSamlChainingMetadataResolver to initialize mutableResolvers with a new ArrayList instead of Collections.emptyList. Big mistake. Also, overrode resolve() to use the mutableResolvers list instead of the (empty) original resolvers list. Added new OpenSamlBatchMetadataResolverDelegate to handle refilter(). Added refilter() to all Batch-ish OpenSaml resolvers. Removed refreshOrInitResolver from filter controller. Not needed. Added refilter() calls in JPAMetadataResolverServiceImpl.reloadFilters. --- .../JPAMetadataResolverServiceImpl.groovy | 22 ++++++---- ...etadataResolverConverterConfiguration.java | 17 ++++++++ .../controller/MetadataFiltersController.java | 29 ------------- .../OpenSamlChainingMetadataResolver.java | 30 ++++++++++++-- ...penSamlFileBackedHTTPMetadataResolver.java | 41 ++++++------------- .../OpenSamlFilesystemMetadataResolver.java | 15 +++++++ ...penSamlResourceBackedMetadataResolver.java | 15 +++++++ .../MetadataResolverConverterServiceImpl.java | 1 - ...JPAMetadataResolverServiceImplTests.groovy | 23 ++++++++--- 9 files changed, 117 insertions(+), 76 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConverterConfiguration.java 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 a4a8451fd..df37471c2 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 @@ -11,20 +11,21 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMet import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlFileBackedHTTPMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlFilesystemMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlResourceBackedMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import groovy.util.logging.Slf4j import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder -import net.shibboleth.utilities.java.support.logic.ScriptedPredicate -import net.shibboleth.utilities.java.support.resolver.ResolverException import net.shibboleth.utilities.java.support.scripting.EvaluableScript import org.opensaml.saml.common.profile.logic.EntityIdPredicate import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver -import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilter import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain +import org.opensaml.saml.metadata.resolver.impl.AbstractBatchMetadataResolver import org.opensaml.saml.saml2.core.Attribute import org.opensaml.saml.saml2.metadata.EntityDescriptor import org.springframework.beans.factory.annotation.Autowired @@ -94,11 +95,16 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { metadataFilterChain.setFilters(metadataFilters) } - if (metadataResolver instanceof RefreshableMetadataResolver) { - try { - ((RefreshableMetadataResolver) metadataResolver).refresh() - } catch (ResolverException e) { - log.warn("error refreshing metadataResolver " + metadataResolverName, e) + if (targetMetadataResolver != null && targetMetadataResolver instanceof AbstractBatchMetadataResolver) { + if (targetMetadataResolver instanceof OpenSamlFileBackedHTTPMetadataResolver) { + (OpenSamlFileBackedHTTPMetadataResolver) targetMetadataResolver.refilter() + } else if (targetMetadataResolver instanceof OpenSamlFilesystemMetadataResolver) { + (OpenSamlFilesystemMetadataResolver) targetMetadataResolver.refilter() + } else if (targetMetadataResolver instanceof OpenSamlResourceBackedMetadataResolver) { + (OpenSamlResourceBackedMetadataResolver) targetMetadataResolver.refilter() + } else { + //TODO: Do something here if we need to refilter other non-Batch resolvers + println("We shouldn't be here. But we are. Why?") } } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConverterConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConverterConfiguration.java new file mode 100644 index 000000000..6380e0018 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/MetadataResolverConverterConfiguration.java @@ -0,0 +1,17 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService; +import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +@Configuration +public class MetadataResolverConverterConfiguration { + @Bean + public MetadataResolverConverterService metadataResolverConverterService() { + return new MetadataResolverConverterServiceImpl(); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java index 632809bea..ce50be62f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java @@ -89,7 +89,6 @@ public ResponseEntity create(@PathVariable String metadataResolverId, @Reques // we reload the filters here after save metadataResolverService.reloadFilters(persistedMr.getName()); - refreshOrInitResolver(metadataResolver); MetadataFilter persistedFilter = newlyPersistedFilter(persistedMr.getMetadataFilters().stream(), createdFilter.getResourceId()); @@ -98,33 +97,6 @@ public ResponseEntity create(@PathVariable String metadataResolverId, @Reques .body(persistedFilter); } - private void refreshOrInitResolver(MetadataResolver resolver) { - List resolvers = ((ChainingMetadataResolver) chainingMetadataResolver).getResolvers(); - resolvers.stream().filter(it -> it.getId().equals(resolver.getResourceId())).forEach(it -> { - if (it instanceof RefreshableMetadataResolver) { - try { - ((RefreshableMetadataResolver) it).refresh(); - } catch (ResolverException e) { - //TODO what should we do if we can't refresh? - } - } else if (it instanceof OpenSamlFunctionDrivenDynamicHTTPMetadataResolver) { - try { - ((OpenSamlFunctionDrivenDynamicHTTPMetadataResolver) it).refresh(); - } catch (ComponentInitializationException e) { - //TODO what should we do if we can't refresh? - } - } else if (it instanceof OpenSamlLocalDynamicMetadataResolver) { - try { - ((OpenSamlLocalDynamicMetadataResolver) it).refresh(); - } catch (ComponentInitializationException e) { - //TODO what should we do if we can't refresh? - } - } else { - //TODO we shouldn't get here, but if we do... throw exception? - } - }); - } - @PutMapping("/Filters/{resourceId}") public ResponseEntity update(@PathVariable String metadataResolverId, @PathVariable String resourceId, @@ -159,7 +131,6 @@ public ResponseEntity update(@PathVariable String metadataResolverId, // TODO: this is wrong metadataResolverService.reloadFilters(metadataResolver.getName()); - refreshOrInitResolver(metadataResolver); return ResponseEntity.ok().body(persistedFilter); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java index aa5f45745..b798e347e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java @@ -4,14 +4,18 @@ import com.google.common.collect.Collections2; import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; +import net.shibboleth.utilities.java.support.component.ComponentSupport; +import net.shibboleth.utilities.java.support.resolver.CriteriaSet; import net.shibboleth.utilities.java.support.resolver.ResolverException; import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver; +import org.opensaml.saml.saml2.metadata.EntityDescriptor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -25,7 +29,7 @@ public class OpenSamlChainingMetadataResolver extends ChainingMetadataResolver { @Nonnull @NonnullElements private List mutableResolvers; public OpenSamlChainingMetadataResolver() { - this.mutableResolvers = Collections.emptyList(); + this.mutableResolvers = new ArrayList<>(); } public OpenSamlChainingMetadataResolver(@Nonnull List mutableResolvers) { @@ -35,7 +39,7 @@ public OpenSamlChainingMetadataResolver(@Nonnull List mutableR @Override public void setResolvers(@Nonnull @NonnullElements final List newResolvers) { if (newResolvers == null || newResolvers.isEmpty()) { - mutableResolvers = Collections.emptyList(); + mutableResolvers = new ArrayList<>(); return; } @@ -54,7 +58,7 @@ protected void doInitialize() throws ComponentInitializationException { super.doInitialize(); if (mutableResolvers == null) { log.warn("OpenSamlChainingMetadataResolver was not configured with any member MetadataResolvers"); - mutableResolvers = Collections.emptyList(); + mutableResolvers = new ArrayList<>(); } } @@ -66,4 +70,24 @@ public void refresh() throws ResolverException { } } } + + @Override + @Nonnull public Iterable resolve(@Nullable final CriteriaSet criteria) throws ResolverException { + ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this); + + for (final MetadataResolver resolver : mutableResolvers) { + try { + final Iterable descriptors = resolver.resolve(criteria); + if (descriptors != null && descriptors.iterator().hasNext()) { + return descriptors; + } + } catch (final ResolverException e) { + log.warn("Error retrieving metadata from resolver of type {}, proceeding to next resolver", + resolver.getClass().getName(), e); + continue; + } + } + + return Collections.emptyList(); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index e74bff535..eac7debe7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -10,7 +10,10 @@ import org.joda.time.DateTime; import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.io.UnmarshallingException; +import org.opensaml.saml.metadata.resolver.filter.FilterException; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -25,17 +28,15 @@ */ public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlFileBackedHTTPMetadataResolver.class); + private static final long MILLISECONDS_IN_ONE_SECOND = 1000; private IndexWriter indexWriter; private FileBackedHttpMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; - - private byte[] cachedMetadataBytes; - private Instant metadataLastFetchedAt; - boolean shouldRefreshMetadata; - XMLObject cachedMetadata; + private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -44,6 +45,7 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); + this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); @@ -82,30 +84,11 @@ protected void initMetadataResolver() throws ComponentInitializationException { indexWriter); } - @Override - protected byte[] fetchMetadata() throws ResolverException { - if (metadataLastFetchedAt == null || shouldRefreshMetadata()) { - this.cachedMetadataBytes = super.fetchMetadata(); - this.metadataLastFetchedAt = Instant.now(); - } - return cachedMetadataBytes; - } - - private boolean shouldRefreshMetadata() { - if ((Instant.now().getEpochSecond() - metadataLastFetchedAt.getEpochSecond()) > (this.getMinRefreshDelay() / MILLISECONDS_IN_ONE_SECOND)) { - shouldRefreshMetadata = true; - } - return shouldRefreshMetadata; - } - - @Override - protected XMLObject unmarshallMetadata(@Nonnull final InputStream metadataInput) - throws UnmarshallingException { - //TODO: This should probably be based on something other than minRefreshDelay - if (cachedMetadata == null || shouldRefreshMetadata) { - this.cachedMetadata = super.unmarshallMetadata(metadataInput); - this.shouldRefreshMetadata = false; + public void refilter() { + try { + batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + } catch (FilterException e) { + logger.error("An error occurred while attempting to filter metadata!", e); } - return this.cachedMetadata; } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java index ad3ee65d9..e20fe632b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java @@ -5,7 +5,10 @@ import net.shibboleth.utilities.java.support.xml.ParserPool; import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; +import org.opensaml.saml.metadata.resolver.filter.FilterException; import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.io.File; @@ -14,9 +17,12 @@ * @author Bill Smith (wsmith@unicon.net) */ public class OpenSamlFilesystemMetadataResolver extends FilesystemMetadataResolver { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlFilesystemMetadataResolver.class); + private IndexWriter indexWriter; private edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; + private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -26,6 +32,7 @@ public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); + this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); @@ -48,4 +55,12 @@ protected void initMetadataResolver() throws ComponentInitializationException { this.sourceResolver.getResourceId(), indexWriter); } + + public void refilter() { + try { + batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + } catch (FilterException e) { + logger.error("An error occurred while attempting to filter metadata!", e); + } + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java index 67cde7971..00bf91c3b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java @@ -5,7 +5,10 @@ import net.shibboleth.utilities.java.support.xml.ParserPool; import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; +import org.opensaml.saml.metadata.resolver.filter.FilterException; import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.io.IOException; @@ -14,9 +17,12 @@ * @author Bill Smith (wsmith@unicon.net) */ public class OpenSamlResourceBackedMetadataResolver extends ResourceBackedMetadataResolver { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlResourceBackedMetadataResolver.class); + private IndexWriter indexWriter; private edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; + private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -26,6 +32,7 @@ public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); + this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); @@ -48,4 +55,12 @@ protected void initMetadataResolver() throws ComponentInitializationException { this.sourceResolver.getResourceId(), indexWriter); } + + public void refilter() { + try { + batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + } catch (FilterException e) { + logger.error("An error occurred while attempting to filter metadata!", e); + } + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java index 4ae0d07d2..e1ed54f82 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java @@ -31,7 +31,6 @@ /** * @author Bill Smith (wsmith@unicon.net) */ -@Service public class MetadataResolverConverterServiceImpl implements MetadataResolverConverterService { @Autowired diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index 381ab3a18..316bfebbd 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -2,15 +2,16 @@ package edu.internet2.tier.shibboleth.admin.ui.service import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConverterConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ClasspathMetadataResource import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.SvnMetadataResource +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver 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 import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import groovy.xml.DOMBuilder @@ -39,10 +40,9 @@ import spock.lang.Specification import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml - @SpringBootTest @DataJpaTest -@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, InternationalizationConfiguration]) +@ContextConfiguration(classes=[CoreShibUiConfiguration, MetadataResolverConverterConfiguration, SearchConfiguration, InternationalizationConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) @@ -65,6 +65,9 @@ class JPAMetadataResolverServiceImplTests extends Specification { @Autowired AttributeUtility attributeUtility + @Autowired + MetadataResolverConverterService mdrConverterService + TestObjectGenerator testObjectGenerator DOMBuilder domBuilder @@ -111,8 +114,13 @@ class JPAMetadataResolverServiceImplTests extends Specification { ''' when: - def mdr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver().with { + def mdr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver().with { + it.resourceId = "testme" it.name = "testme" + it.classpathMetadataResource = new ClasspathMetadataResource().with { + it.file = "metadata/aggregate.xml" + it + } it.metadataFilters.add(new EntityAttributesFilter().with { it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { it.entityAttributesFilterTargetType = EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY @@ -125,12 +133,14 @@ class JPAMetadataResolverServiceImplTests extends Specification { return it } metadataResolverRepository.save(mdr) + ((OpenSamlChainingMetadataResolver) metadataResolver).getResolvers().add(mdrConverterService.convertToOpenSamlRepresentation(mdr)) metadataResolverService.reloadFilters("testme") then: assert metadataResolverRepository.findAll().size() > 0 def ed = metadataResolver.resolveSingle(new CriteriaSet(new EntityIdCriterion('http://test.scaldingspoon.org/test1'))) def resultString = openSamlObjects.marshalToXmlString(ed) + println(resultString) def diff = DiffBuilder.compare(Input.fromString(expectedXML)).withTest(Input.fromString(resultString)).ignoreComments().ignoreWhitespace().build() !diff.hasDifferences() } @@ -302,9 +312,10 @@ class JPAMetadataResolverServiceImplTests extends Specification { it } - return new ChainingMetadataResolver().with { + return new OpenSamlChainingMetadataResolver().with { it.id = 'chain' - it.resolvers = [aggregate] + //it.resolvers = [aggregate] +// it.resolvers = [] it.initialize() it } From 91c381092119f12c6883e2e6ae311b149e3c39d6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 11:42:17 -0400 Subject: [PATCH 08/56] SHIBUI-836 wip --- .../TokenPlaceholderValueResolvingService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java new file mode 100644 index 000000000..3193a51aa --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java @@ -0,0 +1,11 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +/** + * Generic API to resolve values from arbitrary tokenized placeholders such as '%{token.placeholder}' etc. + * + * @author Dmitriy Kopylenko + */ +public interface TokenPlaceholderValueResolvingService { + + String resolveValueFromTokenPlaceholder(String tokenPlaceholder); +} From f4a7b471f413d0975d2e96440abf2b4346f3f91f Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 11:50:15 -0400 Subject: [PATCH 09/56] SHIBUI-836 wip --- ...rtyPlaceholderBasedValueResolvingService.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java new file mode 100644 index 000000000..ceb48f38a --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java @@ -0,0 +1,16 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +/** + * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's default property resolver + * which understands and replaces Shibboleth Idp specific placeholder prefix of '%{' with standard Spring's placeholder + * prefix of '${' before resolving. + * + * If passed it value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. + */ +public class SpringPropertyPlaceholderBasedValueResolvingService implements TokenPlaceholderValueResolvingService { + + @Override + public String resolveValueFromTokenPlaceholder(String tokenPlaceholder) { + return null; + } +} From 76a861f4341042bd4c31285cb7b1219c02295d4b Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 11:52:35 -0400 Subject: [PATCH 10/56] SHIBUI-836: Refactor --- ...> ShibbolethPlaceholderTokenAwareValueResolvingService.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/{SpringPropertyPlaceholderBasedValueResolvingService.java => ShibbolethPlaceholderTokenAwareValueResolvingService.java} (83%) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java similarity index 83% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index ceb48f38a..50e49a6e3 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/SpringPropertyPlaceholderBasedValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -7,7 +7,7 @@ * * If passed it value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. */ -public class SpringPropertyPlaceholderBasedValueResolvingService implements TokenPlaceholderValueResolvingService { +public class ShibbolethPlaceholderTokenAwareValueResolvingService implements TokenPlaceholderValueResolvingService { @Override public String resolveValueFromTokenPlaceholder(String tokenPlaceholder) { From 60f97b5389a203a13e09251df3eda3e8afc0fae6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 12:03:17 -0400 Subject: [PATCH 11/56] SHIBUI-836 wip --- .../admin/ui/ShibbolethUiApplication.java | 1 + ...laceholderResolverComponentsConfiguration.java | 15 +++++++++++++++ ...laceholderTokenAwareValueResolvingService.java | 10 ++++++++++ .../TokenPlaceholderValueResolvingService.java | 7 +++++++ 4 files changed, 33 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index db1779592..6fea0aa99 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; +import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java new file mode 100644 index 000000000..08a0069d4 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java @@ -0,0 +1,15 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.PropertyResolver; + +@Configuration +public class PlaceholderResolverComponentsConfiguration { + + @Bean + public TokenPlaceholderValueResolvingService tokenPlaceholderValueResolvingService(PropertyResolver propertyResolver) { + return TokenPlaceholderValueResolvingService.shibbolethPlaceholderAware(propertyResolver); + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 50e49a6e3..8de170b49 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -1,14 +1,24 @@ package edu.internet2.tier.shibboleth.admin.ui.service; +import org.springframework.core.env.PropertyResolver; + /** * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's default property resolver * which understands and replaces Shibboleth Idp specific placeholder prefix of '%{' with standard Spring's placeholder * prefix of '${' before resolving. * * If passed it value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. + * + * @author Dmitriy Kopylenko */ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements TokenPlaceholderValueResolvingService { + private PropertyResolver propertyResolver; + + ShibbolethPlaceholderTokenAwareValueResolvingService(PropertyResolver propertyResolver) { + this.propertyResolver = propertyResolver; + } + @Override public String resolveValueFromTokenPlaceholder(String tokenPlaceholder) { return null; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java index 3193a51aa..0df2f0ca0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java @@ -1,11 +1,18 @@ package edu.internet2.tier.shibboleth.admin.ui.service; +import org.springframework.core.env.PropertyResolver; + /** * Generic API to resolve values from arbitrary tokenized placeholders such as '%{token.placeholder}' etc. * * @author Dmitriy Kopylenko */ +@FunctionalInterface public interface TokenPlaceholderValueResolvingService { String resolveValueFromTokenPlaceholder(String tokenPlaceholder); + + static TokenPlaceholderValueResolvingService shibbolethPlaceholderAware(PropertyResolver propertyResolver) { + return new ShibbolethPlaceholderTokenAwareValueResolvingService(propertyResolver); + } } From c37f8906e392792fc4c64a41d97e173787b97aff Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 11 Sep 2018 11:08:07 -0500 Subject: [PATCH 12/56] [AS-570] quick fix in initialization --- .../opensaml/OpenSamlResourceBackedMetadataResolver.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java index 00bf91c3b..fd2e945fc 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java @@ -6,6 +6,7 @@ import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +39,9 @@ public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes( this, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); + + //TODO: check if this is the right thing to do + this.setMetadataFilter(new MetadataFilterChain()); } // TODO: this is still probably not the best way to do this? From 4b84cdef8ea4be58a1896ba11fe20d3cb29b3b90 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 16:37:35 -0400 Subject: [PATCH 13/56] SHIBUI-836: wip --- .../admin/ui/ShibbolethUiApplication.java | 6 +++--- ...eholderResolverComponentsConfiguration.java | 6 ++++++ ...eholderTokenAwareValueResolvingService.java | 7 +++++++ .../admin/util/TokenPlaceholderResolvers.java | 18 ++++++++++++++++++ ...tadataResolverValidationServiceTests.groovy | 10 +++++----- 5 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index 6fea0aa99..aa19896ef 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -2,6 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; +import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; @@ -56,9 +57,8 @@ void showMetadataResolversResourceIds(ApplicationStartedEvent e) { System.out.println("IDP HOME: " + idpHome); String rawValue = "%{idp.home}/metadata/file.xml"; - boolean hasToken = rawValue.contains("%{idp.home}"); - String resolvedIdpHome = propertyResolver.resolvePlaceholders("${idp.home}"); - String fullyResolvedDir = rawValue.replace("%{idp.home}", resolvedIdpHome); + String resolved = propertyResolver.resolvePlaceholders(rawValue.replace("%{", "${")); + TokenPlaceholderValueResolvingService service = TokenPlaceholderResolvers.placeholderResolverService(); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java index 08a0069d4..484675e3d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; +import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.PropertyResolver; @@ -12,4 +13,9 @@ public class PlaceholderResolverComponentsConfiguration { public TokenPlaceholderValueResolvingService tokenPlaceholderValueResolvingService(PropertyResolver propertyResolver) { return TokenPlaceholderValueResolvingService.shibbolethPlaceholderAware(propertyResolver); } + + @Bean + public TokenPlaceholderResolvers tokenPlaceholderResolvers(TokenPlaceholderValueResolvingService service) { + return new TokenPlaceholderResolvers(service); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 8de170b49..b4c6fd42a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -2,6 +2,10 @@ import org.springframework.core.env.PropertyResolver; +import java.util.Objects; + +import static java.util.Objects.requireNonNull; + /** * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's default property resolver * which understands and replaces Shibboleth Idp specific placeholder prefix of '%{' with standard Spring's placeholder @@ -21,6 +25,9 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok @Override public String resolveValueFromTokenPlaceholder(String tokenPlaceholder) { + requireNonNull(tokenPlaceholder, "tokenPlaceholder must not be null"); + tokenPlaceholder.replace("%{", "${"); + return null; } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java new file mode 100644 index 000000000..f65737be2 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java @@ -0,0 +1,18 @@ +package edu.internet2.tier.shibboleth.admin.util; + +import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +public class TokenPlaceholderResolvers { + + private static TokenPlaceholderValueResolvingService placeholderResolverService; + + public TokenPlaceholderResolvers(TokenPlaceholderValueResolvingService service) { + TokenPlaceholderResolvers.placeholderResolverService = service; + } + + public static TokenPlaceholderValueResolvingService placeholderResolverService() { + return placeholderResolverService; + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy index d62f07170..eb6486916 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy @@ -11,7 +11,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataRe class MetadataResolverValidationServiceTests extends Specification { def "Validation service with no available validators always returns default valid result"() { - given: 'Sample metadata resolver and validation service with no validators' + given: 'Sample metadata resolver and validation placeholderResolverService with no validators' def resolver = Mock(MetadataResolver) @Subject def validationService = new MetadataResolverValidationService(null) @@ -24,7 +24,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with one validator not supporting the type of resolver returns default valid result"() { - given: 'Sample metadata resolver and validation service with one validator not supporting that type' + given: 'Sample metadata resolver and validation placeholderResolverService with one validator not supporting that type' def resolver = Mock(MetadataResolver) def validator = Mock(MetadataResolverValidator) validator.supports(_) >> false @@ -39,7 +39,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with one validator supporting the type of resolver but fails its validation"() { - given: 'Sample metadata resolver and validation service with one validator supporting that type' + given: 'Sample metadata resolver and validation placeholderResolverService with one validator supporting that type' def resolver = Mock(MetadataResolver) def validator = Mock(MetadataResolverValidator) validator.supports(_) >> true @@ -55,7 +55,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with with two validators supporting the type of resolver, first fails, second passes validation"() { - given: 'Sample metadata resolver and validation service with two validators supporting that type' + given: 'Sample metadata resolver and validation placeholderResolverService with two validators supporting that type' def resolver = Mock(MetadataResolver) def validator1 = Mock(MetadataResolverValidator) validator1.supports(_) >> true @@ -74,7 +74,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with with two validators, only one supporting the type of resolver, passes validation"() { - given: 'Sample metadata resolver and validation service with two validators, with one supporting that type' + given: 'Sample metadata resolver and validation placeholderResolverService with two validators, with one supporting that type' def resolver = Mock(MetadataResolver) def validator1 = Mock(MetadataResolverValidator) validator1.supports(_) >> false From ad2533a24cbd5a039dbb90ecf7113fa41d0a4471 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 16:57:42 -0400 Subject: [PATCH 14/56] SHIBUI-836: wip --- .../OpenSamlFileBackedHTTPMetadataResolver.java | 11 +++++++++-- .../OpenSamlMetadataResolverConstructorHelper.java | 7 ++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 5f4c10905..7327458eb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver; +import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.resolver.ResolverException; import net.shibboleth.utilities.java.support.xml.ParserPool; @@ -13,6 +14,7 @@ import javax.annotation.Nullable; import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** * @author Bill Smith (wsmith@unicon.net) @@ -38,8 +40,12 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes( this, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); - this.setBackupFile(sourceResolver.getBackingFile()); - this.setBackupFileInitNextRefreshDelay(toMillis(sourceResolver.getBackupFileInitNextRefreshDelay())); + //TODO: complete resolving placeholders everywhere + //This might throw runtime exception if unable to resolve placeholders sent from higher layers + this.setBackupFile(placeholderResolverService().resolveValueFromTokenPlaceholder(sourceResolver.getBackingFile())); + this.setBackupFileInitNextRefreshDelay(toMillis(placeholderResolverService() + .resolveValueFromTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()))); + this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile()); //TODO: Where does this get set in OpenSAML land? @@ -63,6 +69,7 @@ protected void processConditionalRetrievalHeaders(HttpResponse response) { protected void initMetadataResolver() throws ComponentInitializationException { super.initMetadataResolver(); + delegate.addIndexedDescriptorsFromBackingStore(this.getBackingStore(), this.sourceResolver.getResourceId(), indexWriter); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java index c5a6845e4..9d0383c11 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java @@ -3,12 +3,14 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes; +import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import net.shibboleth.utilities.java.support.xml.ParserPool; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractDynamicMetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver; import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** * @author Bill Smith (wsmith@unicon.net) @@ -85,9 +87,12 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA //TODO: This takes a ParserPool. We've got a ParserPoolRef in attributes.getParserPoolRef(). Should we use it for anything? reloadingMetadataResolver.setParserPool(parserPool); + //TODO: finish placeholder resolving if (attributes != null) { if (attributes.getExpirationWarningThreshold() != null) { - reloadingMetadataResolver.setExpirationWarningThreshold(toMillis(attributes.getExpirationWarningThreshold())); + reloadingMetadataResolver + .setExpirationWarningThreshold(toMillis(placeholderResolverService() + .resolveValueFromTokenPlaceholder(attributes.getExpirationWarningThreshold()))); } if (attributes.getMaxRefreshDelay() != null) { reloadingMetadataResolver.setMaxRefreshDelay(toMillis(attributes.getMaxRefreshDelay())); From 5ce50ffd532b3a17d1ad6ede13b7aba1152601df Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Sep 2018 17:04:38 -0400 Subject: [PATCH 15/56] SHIBUI-836: polishing --- .../MetadataResolverValidationServiceTests.groovy | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy index eb6486916..d62f07170 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverValidationServiceTests.groovy @@ -11,7 +11,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataRe class MetadataResolverValidationServiceTests extends Specification { def "Validation service with no available validators always returns default valid result"() { - given: 'Sample metadata resolver and validation placeholderResolverService with no validators' + given: 'Sample metadata resolver and validation service with no validators' def resolver = Mock(MetadataResolver) @Subject def validationService = new MetadataResolverValidationService(null) @@ -24,7 +24,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with one validator not supporting the type of resolver returns default valid result"() { - given: 'Sample metadata resolver and validation placeholderResolverService with one validator not supporting that type' + given: 'Sample metadata resolver and validation service with one validator not supporting that type' def resolver = Mock(MetadataResolver) def validator = Mock(MetadataResolverValidator) validator.supports(_) >> false @@ -39,7 +39,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with one validator supporting the type of resolver but fails its validation"() { - given: 'Sample metadata resolver and validation placeholderResolverService with one validator supporting that type' + given: 'Sample metadata resolver and validation service with one validator supporting that type' def resolver = Mock(MetadataResolver) def validator = Mock(MetadataResolverValidator) validator.supports(_) >> true @@ -55,7 +55,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with with two validators supporting the type of resolver, first fails, second passes validation"() { - given: 'Sample metadata resolver and validation placeholderResolverService with two validators supporting that type' + given: 'Sample metadata resolver and validation service with two validators supporting that type' def resolver = Mock(MetadataResolver) def validator1 = Mock(MetadataResolverValidator) validator1.supports(_) >> true @@ -74,7 +74,7 @@ class MetadataResolverValidationServiceTests extends Specification { } def "Validation service with with two validators, only one supporting the type of resolver, passes validation"() { - given: 'Sample metadata resolver and validation placeholderResolverService with two validators, with one supporting that type' + given: 'Sample metadata resolver and validation service with two validators, with one supporting that type' def resolver = Mock(MetadataResolver) def validator1 = Mock(MetadataResolverValidator) validator1.supports(_) >> false From 1350872b12f3a677fb5bda9fb8a85cfeb3d21992 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 11 Sep 2018 15:13:19 -0700 Subject: [PATCH 16/56] [SHIBUI-570] Removed Batch resolver delegate. Added Refilterable interface. Implemented interface where appropriate. Added initialization for metadataFilterChain. Saving filters is much speedier now for these resolver types. --- ...OpenSamlBatchMetadataResolverDelegate.java | 19 ------------------ ...penSamlFileBackedHTTPMetadataResolver.java | 20 ++++++++----------- .../OpenSamlFilesystemMetadataResolver.java | 13 ++++++++---- ...penSamlResourceBackedMetadataResolver.java | 10 ++++++---- .../resolvers/opensaml/Refilterable.java | 16 +++++++++++++++ 5 files changed, 39 insertions(+), 39 deletions(-) delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/Refilterable.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java deleted file mode 100644 index 855de838f..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlBatchMetadataResolverDelegate.java +++ /dev/null @@ -1,19 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml; - -import org.opensaml.core.xml.XMLObject; -import org.opensaml.saml.metadata.resolver.impl.AbstractBatchMetadataResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Bill Smith (wsmith@unicon.net) - */ -public class OpenSamlBatchMetadataResolverDelegate extends AbstractBatchMetadataResolver { - private static final Logger logger = LoggerFactory.getLogger(OpenSamlBatchMetadataResolverDelegate.class); - - //TODO: Not sure this delegate is really buying us anything.. other than to get this one line in to a shared class. - //Maybe we'll do more in here later? - public void refilter(AbstractBatchMetadataResolver.BatchEntityBackingStore backingStore, XMLObject filteredMetadata) { - backingStore.setCachedFilteredMetadata(filteredMetadata); - } -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index eac7debe7..d0a9b6ff4 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -8,35 +8,27 @@ import org.apache.http.impl.client.HttpClients; import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; -import org.opensaml.core.xml.XMLObject; -import org.opensaml.core.xml.io.UnmarshallingException; import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.io.InputStream; -import java.time.Instant; - import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; /** * @author Bill Smith (wsmith@unicon.net) */ -public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver { +public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver implements Refilterable { private static final Logger logger = LoggerFactory.getLogger(OpenSamlFileBackedHTTPMetadataResolver.class); - private static final long MILLISECONDS_IN_ONE_SECOND = 1000; - private IndexWriter indexWriter; private FileBackedHttpMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; - private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -45,7 +37,6 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); - this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); @@ -58,6 +49,8 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, this.setBackupFileInitNextRefreshDelay(toMillis(sourceResolver.getBackupFileInitNextRefreshDelay())); this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile()); + this.setMetadataFilter(new MetadataFilterChain()); + //TODO: Where does this get set in OpenSAML land? // sourceResolver.getMetadataURL(); } @@ -84,9 +77,12 @@ protected void initMetadataResolver() throws ComponentInitializationException { indexWriter); } + /** + * {@inheritDoc} + */ public void refilter() { try { - batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + this.getBackingStore().setCachedFilteredMetadata(filterMetadata(getCachedOriginalMetadata())); } catch (FilterException e) { logger.error("An error occurred while attempting to filter metadata!", e); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java index e20fe632b..b4fb6d578 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java @@ -6,6 +6,7 @@ import org.apache.lucene.index.IndexWriter; import org.joda.time.DateTime; import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,13 +17,13 @@ /** * @author Bill Smith (wsmith@unicon.net) */ -public class OpenSamlFilesystemMetadataResolver extends FilesystemMetadataResolver { +public class OpenSamlFilesystemMetadataResolver extends FilesystemMetadataResolver implements Refilterable { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlFilesystemMetadataResolver.class); private IndexWriter indexWriter; private edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; - private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -32,12 +33,13 @@ public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); - this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes( this, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); + + this.setMetadataFilter(new MetadataFilterChain()); } // TODO: this is still probably not the best way to do this? @@ -56,9 +58,12 @@ protected void initMetadataResolver() throws ComponentInitializationException { indexWriter); } + /** + * {@inheritDoc} + */ public void refilter() { try { - batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + this.getBackingStore().setCachedFilteredMetadata(filterMetadata(getCachedOriginalMetadata())); } catch (FilterException e) { logger.error("An error occurred while attempting to filter metadata!", e); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java index fd2e945fc..0a4b2a7f2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java @@ -17,13 +17,13 @@ /** * @author Bill Smith (wsmith@unicon.net) */ -public class OpenSamlResourceBackedMetadataResolver extends ResourceBackedMetadataResolver { +public class OpenSamlResourceBackedMetadataResolver extends ResourceBackedMetadataResolver implements Refilterable { + private static final Logger logger = LoggerFactory.getLogger(OpenSamlResourceBackedMetadataResolver.class); private IndexWriter indexWriter; private edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver sourceResolver; private OpenSamlMetadataResolverDelegate delegate; - private OpenSamlBatchMetadataResolverDelegate batchDelegate; public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, IndexWriter indexWriter, @@ -33,7 +33,6 @@ public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, this.indexWriter = indexWriter; this.sourceResolver = sourceResolver; this.delegate = new OpenSamlMetadataResolverDelegate(); - this.batchDelegate = new OpenSamlBatchMetadataResolverDelegate(); this.setId(sourceResolver.getResourceId()); @@ -60,9 +59,12 @@ protected void initMetadataResolver() throws ComponentInitializationException { indexWriter); } + /** + * {@inheritDoc} + */ public void refilter() { try { - batchDelegate.refilter(this.getBackingStore(), filterMetadata(getCachedOriginalMetadata())); + this.getBackingStore().setCachedFilteredMetadata(filterMetadata(getCachedOriginalMetadata())); } catch (FilterException e) { logger.error("An error occurred while attempting to filter metadata!", e); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/Refilterable.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/Refilterable.java new file mode 100644 index 000000000..339a3b8e3 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/Refilterable.java @@ -0,0 +1,16 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml; + +/** + * Indicates that the resolver implementing this interface is a resolver that allows for its metadata to be + * filtered multiple times. + * + * @author Bill Smith (wsmith@unicon.net) + */ +public interface Refilterable { + + /** + * Reapply this resolver's filters to its cached, unfiltered metadata, and set the result back to its cached, + * filtered metadata. + */ + void refilter(); +} \ No newline at end of file From 670fb5ca9103494ea14775ce17fd964df21720d5 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 11 Sep 2018 15:24:20 -0700 Subject: [PATCH 17/56] [SHIBUI-570] Removed duplicate method. --- .../OpenSamlChainingMetadataResolver.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java index 0cc2102c1..3213736a6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlChainingMetadataResolver.java @@ -90,24 +90,4 @@ public void refresh() throws ResolverException { } } } - - @Override - @Nonnull public Iterable resolve(@Nullable final CriteriaSet criteria) throws ResolverException { - ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this); - - for (final MetadataResolver resolver : mutableResolvers) { - try { - final Iterable descriptors = resolver.resolve(criteria); - if (descriptors != null && descriptors.iterator().hasNext()) { - return descriptors; - } - } catch (final ResolverException e) { - log.warn("Error retrieving metadata from resolver of type {}, proceeding to next resolver", - resolver.getClass().getName(), e); - continue; - } - } - - return Collections.emptyList(); - } } From 31f2fc745a7584958d8019fbfbfe9807da93700d Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 09:37:59 -0400 Subject: [PATCH 18/56] SHIBUI-836: wip --- ...aceholderValueResolvingServiceTests.groovy | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy new file mode 100644 index 000000000..fc0f06c1d --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy @@ -0,0 +1,25 @@ +package edu.internet2.tier.shibboleth.admin.ui.service + +import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification +import spock.lang.Subject + +@ContextConfiguration(classes=[PlaceholderResolverComponentsConfiguration]) +class TokenPlaceholderValueResolvingServiceTests extends Specification { + + @Autowired + @Subject + TokenPlaceholderValueResolvingService placeholderValueResolvingService + + def "resolves correctly existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { + when: + def idpHome = placeholderValueResolvingService.resolveValueFromTokenPlaceholder('%{idp.home}') + + then: + idpHome + } + + +} From 4916b94013a649b100a874d0471ba5fc404fff6e Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 10:46:04 -0400 Subject: [PATCH 19/56] SHIBUI-836: tests wip --- ...holderTokenAwareValueResolvingService.java | 21 ++++++++--- ...TokenPlaceholderValueResolvingService.java | 2 +- ...aceholderValueResolvingServiceTests.groovy | 37 +++++++++++++++---- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index b4c6fd42a..5af4e793e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -19,15 +19,26 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok private PropertyResolver propertyResolver; + private static final String SHIB_IDP_PLACEHOLDER_PREEFIX = "%{"; + + private static final String STANDART_PLACEHOLDER_PREFIX = "${"; + ShibbolethPlaceholderTokenAwareValueResolvingService(PropertyResolver propertyResolver) { this.propertyResolver = propertyResolver; } @Override - public String resolveValueFromTokenPlaceholder(String tokenPlaceholder) { - requireNonNull(tokenPlaceholder, "tokenPlaceholder must not be null"); - tokenPlaceholder.replace("%{", "${"); - - return null; + public String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder) { + requireNonNull(potentialTokenPlaceholder, "potentialTokenPlaceholder must not be null"); + if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREEFIX)) { + String normalizedTokenPlaceholder = + potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREEFIX, STANDART_PLACEHOLDER_PREFIX); + //This call might result in IllegalArgumentException if it's unable to resolve passed in property(ies) + //e.g. due to bad data sent, etc. This is OK, as passing correct data and ensuring that + //property values are correctly set is the responsibility of the software operator + return this.propertyResolver.resolveRequiredPlaceholders(normalizedTokenPlaceholder); + } + //No token placeholders, just return the given data as is + return potentialTokenPlaceholder; } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java index 0df2f0ca0..264ccc935 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java @@ -10,7 +10,7 @@ @FunctionalInterface public interface TokenPlaceholderValueResolvingService { - String resolveValueFromTokenPlaceholder(String tokenPlaceholder); + String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder); static TokenPlaceholderValueResolvingService shibbolethPlaceholderAware(PropertyResolver propertyResolver) { return new ShibbolethPlaceholderTokenAwareValueResolvingService(propertyResolver); diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy index fc0f06c1d..1046bc9f1 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy @@ -2,24 +2,47 @@ package edu.internet2.tier.shibboleth.admin.ui.service import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.util.TestPropertyValues +import org.springframework.core.env.ConfigurableEnvironment import org.springframework.test.context.ContextConfiguration + import spock.lang.Specification import spock.lang.Subject -@ContextConfiguration(classes=[PlaceholderResolverComponentsConfiguration]) +import static edu.internet2.tier.shibboleth.admin.ui.service.TestProps.IDP_HOME +import static edu.internet2.tier.shibboleth.admin.ui.service.TestProps.REFRESH_INTERVAL + + +/** + * @author Dmitriy Kopylenko + */ +@ContextConfiguration(classes = [PlaceholderResolverComponentsConfiguration]) class TokenPlaceholderValueResolvingServiceTests extends Specification { @Autowired @Subject - TokenPlaceholderValueResolvingService placeholderValueResolvingService + TokenPlaceholderValueResolvingService serviceUnderTest - def "resolves correctly existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { - when: - def idpHome = placeholderValueResolvingService.resolveValueFromTokenPlaceholder('%{idp.home}') + @Autowired + ConfigurableEnvironment environment - then: - idpHome + def setup() { + def propPairs = ["idp.home=$IDP_HOME".toString(), "refresh.interval=$REFRESH_INTERVAL".toString()] + TestPropertyValues.of(propPairs).applyTo(environment) } + def "resolves correctly existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { + when: 'Valid placeholder token is passed for which property values are defined' + def idpHome = serviceUnderTest.resolveValueFromTokenPlaceholder('%{idp.home}') + def refreshInterval = serviceUnderTest.resolveValueFromTokenPlaceholder('%{refresh.interval}') + + then: 'Correct property value resolution is performed' + idpHome == IDP_HOME + refreshInterval == REFRESH_INTERVAL + } +} +class TestProps { + static final IDP_HOME = '/tmp/test/idp' + static final REFRESH_INTERVAL = 'PT5M' } From 72eaf873e06eb2be07ebf3dcc315c1f2bb567da3 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 11:38:54 -0400 Subject: [PATCH 20/56] SHIBUI-836: clean up --- .../admin/ui/ShibbolethUiApplication.java | 19 ------------ ...lverPropertyPlaceholderValuesReplacer.java | 17 ----------- ...ertyPlaceholderValuesResolvingService.java | 29 ------------------- 3 files changed, 65 deletions(-) delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java delete mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index aa19896ef..1fc74cf9d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -1,10 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; -import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; -import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; @@ -13,8 +10,6 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Profile; import org.springframework.context.event.EventListener; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.env.PropertyResolver; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.stereotype.Component; @@ -41,24 +36,10 @@ public static class MetadataResolversResourceIdEmitter { @Autowired MetadataResolverRepository metadataResolverRepository; - @Value("${idp.home}") - String idpHome; - - @Autowired - PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer; - - @Autowired - PropertyResolver propertyResolver; - @EventListener void showMetadataResolversResourceIds(ApplicationStartedEvent e) { metadataResolverRepository.findAll() .forEach(it -> System.out.println(String.format("MetadataResolver [%s: %s]", it.getName(), it.getResourceId()))); - - System.out.println("IDP HOME: " + idpHome); - String rawValue = "%{idp.home}/metadata/file.xml"; - String resolved = propertyResolver.resolvePlaceholders(rawValue.replace("%{", "${")); - TokenPlaceholderValueResolvingService service = TokenPlaceholderResolvers.placeholderResolverService(); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java deleted file mode 100644 index 10887e97f..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesReplacer.java +++ /dev/null @@ -1,17 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; - -/** - * An SPI to resolve and convert data for different types of {@link MetadataResolver}s from possible provided '%{}' placeholders - *

- * Typical usage is - multiple replacers for concrete type of resolvers are configured in Spring Application Context, - * aggregated by {@link MetadataResolverPropertyPlaceholderValuesResolvingService} facade and then that facade is injected into upstream consumers of it - * such as REST controllers, etc. - * - * @author Dmitriy Kopylenko - */ -public interface MetadataResolverPropertyPlaceholderValuesReplacer { - - boolean supports(T metadataResolver); - - void replacePlaceholderValuesIfResolvableOrFail(T metadataResolver); -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java deleted file mode 100644 index e7639cfde..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolverPropertyPlaceholderValuesResolvingService.java +++ /dev/null @@ -1,29 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; - -import java.util.ArrayList; -import java.util.List; - -/** - * A facade that aggregates {@link MetadataResolverPropertyPlaceholderValuesReplacer}s available to call just one of them supporting the type of a given resolver. - * If no {@link MetadataResolverPropertyPlaceholderValuesReplacer}s are configured, considers a noop. - * - * Uses chain-of-responsibility design pattern - * - * @author Dmitriy Kopylenko - */ -public class MetadataResolverPropertyPlaceholderValuesResolvingService { - - private List> replacers; - - public MetadataResolverPropertyPlaceholderValuesResolvingService(List> replacers) { - this.replacers = replacers != null ? replacers : new ArrayList<>(); - } - - public void replacePlacehoderValuesOrFail(T metadataResolver) { - this.replacers - .stream() - .filter(r -> r.supports(metadataResolver)) - .findFirst() - .ifPresent(r -> r.replacePlaceholderValuesIfResolvableOrFail(metadataResolver)); - } -} From 978a676300c083ec65affd1992491c9358a43303 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 11:42:06 -0400 Subject: [PATCH 21/56] SHIBUI-836: clean up --- ...TokenPlaceholderValueResolvingServiceTests.groovy | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy index 1046bc9f1..0362d50e2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy @@ -9,10 +9,6 @@ import org.springframework.test.context.ContextConfiguration import spock.lang.Specification import spock.lang.Subject -import static edu.internet2.tier.shibboleth.admin.ui.service.TestProps.IDP_HOME -import static edu.internet2.tier.shibboleth.admin.ui.service.TestProps.REFRESH_INTERVAL - - /** * @author Dmitriy Kopylenko */ @@ -26,6 +22,9 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { @Autowired ConfigurableEnvironment environment + static final IDP_HOME = '/tmp/test/idp' + static final REFRESH_INTERVAL = 'PT5M' + def setup() { def propPairs = ["idp.home=$IDP_HOME".toString(), "refresh.interval=$REFRESH_INTERVAL".toString()] TestPropertyValues.of(propPairs).applyTo(environment) @@ -41,8 +40,3 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { refreshInterval == REFRESH_INTERVAL } } - -class TestProps { - static final IDP_HOME = '/tmp/test/idp' - static final REFRESH_INTERVAL = 'PT5M' -} From f0703063fb89c0170c2a78a9526f9512efc910f1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 12:10:01 -0400 Subject: [PATCH 22/56] SHIBUI-836: tests --- ...holderTokenAwareValueResolvingService.java | 9 +++- ...aceholderValueResolvingServiceTests.groovy | 41 ++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 5af4e793e..baca61749 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -36,7 +36,14 @@ public String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder) //This call might result in IllegalArgumentException if it's unable to resolve passed in property(ies) //e.g. due to bad data sent, etc. This is OK, as passing correct data and ensuring that //property values are correctly set is the responsibility of the software operator - return this.propertyResolver.resolveRequiredPlaceholders(normalizedTokenPlaceholder); + String resolved = this.propertyResolver.resolveRequiredPlaceholders(normalizedTokenPlaceholder); + + //Indicates that malformed values such as %{incomplete.token are passed. Spring won't resolve and return + //the value as is. Just change it back to the original shib-style token and return. + if(resolved.equals(normalizedTokenPlaceholder)) { + return resolved.replace(STANDART_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREEFIX); + } + return resolved; } //No token placeholders, just return the given data as is return potentialTokenPlaceholder; diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy index 0362d50e2..36837694c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy @@ -24,6 +24,7 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { static final IDP_HOME = '/tmp/test/idp' static final REFRESH_INTERVAL = 'PT5M' + static final PLAIN_VALUE = 'Plain String value' def setup() { def propPairs = ["idp.home=$IDP_HOME".toString(), "refresh.interval=$REFRESH_INTERVAL".toString()] @@ -31,7 +32,7 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { } def "resolves correctly existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { - when: 'Valid placeholder token is passed for which property values are defined' + when: 'Valid placeholder token is passed in for which property values are defined' def idpHome = serviceUnderTest.resolveValueFromTokenPlaceholder('%{idp.home}') def refreshInterval = serviceUnderTest.resolveValueFromTokenPlaceholder('%{refresh.interval}') @@ -39,4 +40,42 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { idpHome == IDP_HOME refreshInterval == REFRESH_INTERVAL } + + def "returns value as is if no well-formed shibboleth idp style placeholder tokens: %{} are passed in"() { + when: 'Plain value without placeholder token is passed in' + def idpHome = serviceUnderTest.resolveValueFromTokenPlaceholder(IDP_HOME) + def plainValue = serviceUnderTest.resolveValueFromTokenPlaceholder(PLAIN_VALUE) + + then: 'Value returned as is' + idpHome == IDP_HOME + plainValue == PLAIN_VALUE + + when: 'Malformed placeholder value is passed in' + plainValue = serviceUnderTest.resolveValueFromTokenPlaceholder('%{malformed.value') + + then: + plainValue == '%{malformed.value' + } + + def "Throws IllegalArgumentException for unresolvable properties"() { + when: 'Valid placeholder token is passed in for which property values are undefined' + serviceUnderTest.resolveValueFromTokenPlaceholder("%{i.am.not.defined}") + + then: + thrown IllegalArgumentException + + when: 'Combination of resolvable and unresolvable tokens are passed in' + serviceUnderTest.resolveValueFromTokenPlaceholder("%{idp.home}/%{i.am.not.defined}") + + then: + thrown IllegalArgumentException + } + + def "resolves correctly combination of existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { + when: 'Valid placeholder token is passed in for which property values are defined' + def combinedValue = serviceUnderTest.resolveValueFromTokenPlaceholder('%{idp.home} AND %{refresh.interval}') + + then: 'Correct combined property values resolution is performed' + combinedValue == "$IDP_HOME AND $REFRESH_INTERVAL" + } } From 640423aad9c2ad6e56e796bf43af9e74c29132a5 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 12 Sep 2018 09:16:49 -0700 Subject: [PATCH 23/56] [SHIBUI-570] Dropped min refresh down to 30S. --- .../tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index 7510f9929..7c3eef273 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -460,7 +460,7 @@ class TestObjectGenerator { it.metadataURL = 'https://idp.unicon.net/idp/shibboleth' it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { - it.minRefreshDelay = 'PT5M' + it.minRefreshDelay = 'PT30S' it.maxRefreshDelay = 'PT1H' it.refreshDelayFactor = 0.75 it From 0721845e81fe808af2b82bb3a607a3b57ecac085 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 12 Sep 2018 09:38:20 -0700 Subject: [PATCH 24/56] [SHIBUI-570] Removed specifying delay, opting for defaults instead. --- .../tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy | 3 --- backend/src/test/resources/conf/278.2.xml | 5 +---- backend/src/test/resources/conf/278.xml | 5 +---- backend/src/test/resources/conf/532.xml | 5 +---- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index 7c3eef273..6a7d0e1cf 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -460,9 +460,6 @@ class TestObjectGenerator { it.metadataURL = 'https://idp.unicon.net/idp/shibboleth' it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { - it.minRefreshDelay = 'PT30S' - it.maxRefreshDelay = 'PT1H' - it.refreshDelayFactor = 0.75 it } it diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml index 2b71b5ed1..5a34f756b 100644 --- a/backend/src/test/resources/conf/278.2.xml +++ b/backend/src/test/resources/conf/278.2.xml @@ -39,10 +39,7 @@ + metadataURL="https://idp.unicon.net/idp/shibboleth"> diff --git a/backend/src/test/resources/conf/278.xml b/backend/src/test/resources/conf/278.xml index b244bf6b6..a337f72d7 100644 --- a/backend/src/test/resources/conf/278.xml +++ b/backend/src/test/resources/conf/278.xml @@ -32,10 +32,7 @@ + metadataURL="https://idp.unicon.net/idp/shibboleth"> diff --git a/backend/src/test/resources/conf/532.xml b/backend/src/test/resources/conf/532.xml index bf4ce340b..85fead908 100644 --- a/backend/src/test/resources/conf/532.xml +++ b/backend/src/test/resources/conf/532.xml @@ -8,8 +8,5 @@ + metadataURL="https://idp.unicon.net/idp/shibboleth" /> From 8ac52b8e9c04c52fba1d2c6c467bc4dbdd4056c9 Mon Sep 17 00:00:00 2001 From: Jj! Date: Wed, 12 Sep 2018 11:48:37 -0500 Subject: [PATCH 25/56] [AS-570] WIP --- .../admin/ui/service/JPAMetadataResolverServiceImpl.groovy | 2 +- .../admin/ui/controller/MetadataFiltersController.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) 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 df37471c2..186dd0116 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 @@ -56,7 +56,7 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { void reloadFilters(String metadataResolverName) { ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver) metadataResolver MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverName } - edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName) + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByResourceId(metadataResolverName) if (targetMetadataResolver && targetMetadataResolver.getMetadataFilter() instanceof MetadataFilterChain) { MetadataFilterChain metadataFilterChain = (MetadataFilterChain) targetMetadataResolver.getMetadataFilter() diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java index ce50be62f..431632023 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java @@ -88,7 +88,7 @@ public ResponseEntity create(@PathVariable String metadataResolverId, @Reques MetadataResolver persistedMr = repository.save(metadataResolver); // we reload the filters here after save - metadataResolverService.reloadFilters(persistedMr.getName()); + metadataResolverService.reloadFilters(persistedMr.getResourceId()); MetadataFilter persistedFilter = newlyPersistedFilter(persistedMr.getMetadataFilters().stream(), createdFilter.getResourceId()); @@ -130,7 +130,7 @@ public ResponseEntity update(@PathVariable String metadataResolverId, MetadataFilter persistedFilter = filterRepository.save(filterTobeUpdated); // TODO: this is wrong - metadataResolverService.reloadFilters(metadataResolver.getName()); + metadataResolverService.reloadFilters(metadataResolver.getResourceId()); return ResponseEntity.ok().body(persistedFilter); } From c688c14d2c83965d92ff0fe5401d98d0526cfc03 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 14:30:21 -0400 Subject: [PATCH 26/56] SHIBUI-836: wip --- ...hibbolethPlaceholderTokenAwareValueResolvingService.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index baca61749..242027773 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -29,7 +29,11 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok @Override public String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder) { - requireNonNull(potentialTokenPlaceholder, "potentialTokenPlaceholder must not be null"); + //Ignore nulls. + if(potentialTokenPlaceholder == null) { + return potentialTokenPlaceholder; + } + if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREEFIX)) { String normalizedTokenPlaceholder = potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREEFIX, STANDART_PLACEHOLDER_PREFIX); From 3e8d197ded3bf62af793bb3dff99d8cfbed557eb Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 12 Sep 2018 11:36:54 -0700 Subject: [PATCH 27/56] [SHIBUI-570] Replaced references to metadataResolverName with ResourceId. Replaced ChainingMetadataResolver with OpenSaml. Replaced instanceof with smaller one based on Refilterable. Moved updateChainingMetadataResolver to Util class. Updated unit tests that create EntityAttributesFilters to create Targets with valid values for regex and condition script. Unit tests WIP. --- .../JPAMetadataResolverServiceImpl.groovy | 31 +++++++------------ .../MetadataResolversController.java | 18 ++++------- .../OpenSamlChainingMetadataResolverUtil.java | 20 ++++++++++++ ...taFiltersControllerIntegrationTests.groovy | 18 ++++++++--- .../admin/ui/util/TestObjectGenerator.groovy | 19 ++++++++++-- 5 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/OpenSamlChainingMetadataResolverUtil.java 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 186dd0116..ec201d00b 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 @@ -11,9 +11,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMet import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlFileBackedHTTPMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlFilesystemMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlResourceBackedMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.Refilterable import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import groovy.util.logging.Slf4j @@ -21,11 +20,9 @@ import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.utilities.java.support.scripting.EvaluableScript import org.opensaml.saml.common.profile.logic.EntityIdPredicate -import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilter import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain -import org.opensaml.saml.metadata.resolver.impl.AbstractBatchMetadataResolver import org.opensaml.saml.saml2.core.Attribute import org.opensaml.saml.saml2.metadata.EntityDescriptor import org.springframework.beans.factory.annotation.Autowired @@ -53,10 +50,10 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { // TODO: enhance @Override - void reloadFilters(String metadataResolverName) { - ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver) metadataResolver - MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverName } - edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByResourceId(metadataResolverName) + void reloadFilters(String metadataResolverResourceId) { + OpenSamlChainingMetadataResolver chainingMetadataResolver = (OpenSamlChainingMetadataResolver) metadataResolver + MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverResourceId } + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByResourceId(metadataResolverResourceId) if (targetMetadataResolver && targetMetadataResolver.getMetadataFilter() instanceof MetadataFilterChain) { MetadataFilterChain metadataFilterChain = (MetadataFilterChain) targetMetadataResolver.getMetadataFilter() @@ -95,17 +92,11 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { metadataFilterChain.setFilters(metadataFilters) } - if (targetMetadataResolver != null && targetMetadataResolver instanceof AbstractBatchMetadataResolver) { - if (targetMetadataResolver instanceof OpenSamlFileBackedHTTPMetadataResolver) { - (OpenSamlFileBackedHTTPMetadataResolver) targetMetadataResolver.refilter() - } else if (targetMetadataResolver instanceof OpenSamlFilesystemMetadataResolver) { - (OpenSamlFilesystemMetadataResolver) targetMetadataResolver.refilter() - } else if (targetMetadataResolver instanceof OpenSamlResourceBackedMetadataResolver) { - (OpenSamlResourceBackedMetadataResolver) targetMetadataResolver.refilter() - } else { - //TODO: Do something here if we need to refilter other non-Batch resolvers - println("We shouldn't be here. But we are. Why?") - } + if (targetMetadataResolver != null && targetMetadataResolver instanceof Refilterable) { + (Refilterable) targetMetadataResolver.refilter() + } else { + //TODO: Do something here if we need to refilter other non-Batch resolvers + println("We shouldn't be here. But we are. Why?") } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index 7388679da..47458273d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -3,15 +3,16 @@ import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidationService; +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.service.IndexWriterService; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService; +import edu.internet2.tier.shibboleth.admin.util.OpenSamlChainingMetadataResolverUtil; import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.resolver.ResolverException; -import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -36,7 +37,6 @@ import java.io.IOException; import java.io.StringWriter; import java.net.URI; -import java.util.ArrayList; import java.util.List; import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidator.ValidationResult; @@ -120,19 +120,12 @@ public ResponseEntity create(@RequestBody MetadataResolver newResolver) throw //TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets // n valid response. This operation is not atomic. Should we return an error here? - updateChainingMetadataResolver(persistedResolver); + org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); + OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation); return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver); } - private void updateChainingMetadataResolver(MetadataResolver persistedResolver) throws IOException, ResolverException, ComponentInitializationException { - org.opensaml.saml.metadata.resolver.MetadataResolver openSamlResolver = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); - List resolverList = new ArrayList<>(((ChainingMetadataResolver) chainingMetadataResolver).getResolvers()); - resolverList.removeIf(resolver -> resolver.getId().equals(persistedResolver.getResourceId())); - resolverList.add(openSamlResolver); - ((ChainingMetadataResolver) chainingMetadataResolver).setResolvers(resolverList); - } - @PutMapping("/MetadataResolvers/{resourceId}") @Transactional public ResponseEntity update(@PathVariable String resourceId, @RequestBody MetadataResolver updatedResolver) throws IOException, ResolverException, ComponentInitializationException { @@ -155,7 +148,8 @@ public ResponseEntity update(@PathVariable String resourceId, @RequestBody Me MetadataResolver persistedResolver = resolverRepository.save(updatedResolver); - updateChainingMetadataResolver(persistedResolver); + org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver); + OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation); return ResponseEntity.ok(persistedResolver); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/OpenSamlChainingMetadataResolverUtil.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/OpenSamlChainingMetadataResolverUtil.java new file mode 100644 index 000000000..81b8f3675 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/OpenSamlChainingMetadataResolverUtil.java @@ -0,0 +1,20 @@ +package edu.internet2.tier.shibboleth.admin.util; + +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver; +import org.opensaml.saml.metadata.resolver.MetadataResolver; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Bill Smith (wsmith@unicon.net) + */ +public class OpenSamlChainingMetadataResolverUtil { + + public static void updateChainingMetadataResolver(OpenSamlChainingMetadataResolver chainingMetadataResolver, MetadataResolver openSamlResolver) { + List resolverList = new ArrayList<>(chainingMetadataResolver.getResolvers()); + resolverList.removeIf(resolver -> resolver.getId().equals(openSamlResolver.getId())); + resolverList.add(openSamlResolver); + chainingMetadataResolver.setResolvers(resolverList); + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerIntegrationTests.groovy index 06f9d0ca0..7f7beefe7 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerIntegrationTests.groovy @@ -3,12 +3,14 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.SerializationFeature import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.util.AttributeUtility +import edu.internet2.tier.shibboleth.admin.util.OpenSamlChainingMetadataResolverUtil import groovy.json.JsonOutput import groovy.json.JsonSlurper -import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest @@ -38,6 +40,12 @@ class MetadataFiltersControllerIntegrationTests extends Specification { @Autowired AttributeUtility attributeUtility + @Autowired + MetadataResolverConverterService metadataResolverConverterService + + @Autowired + MetadataResolver chainingMetadataResolver + ObjectMapper mapper TestObjectGenerator generator @@ -63,7 +71,8 @@ class MetadataFiltersControllerIntegrationTests extends Specification { def filterResourceId = resolver.metadataFilters[0].resourceId def resolverResourceId = resolver.resourceId metadataResolverRepository.save(resolver) - + MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(resolver) + OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation) when: 'GET request is made with resource Id matching the existing filter' def result = this.restTemplate.getForEntity("$BASE_URI/$resolverResourceId/Filters/$filterResourceId", String) @@ -86,7 +95,8 @@ class MetadataFiltersControllerIntegrationTests extends Specification { def filterResourceId = resolver.metadataFilters[0].resourceId def resolverResourceId = resolver.resourceId metadataResolverRepository.save(resolver) - + MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(resolver) + OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation) when: 'GET request is made with resource Id matching the existing filter' def result = this.restTemplate.getForEntity("$BASE_URI/$resolverResourceId/Filters/$filterResourceId", String) @@ -182,7 +192,7 @@ class MetadataFiltersControllerIntegrationTests extends Specification { static class Config { @Bean MetadataResolver metadataResolver() { - new ChainingMetadataResolver().with { + new OpenSamlChainingMetadataResolver().with { it.id = 'tester' it.initialize() return it diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index 6a7d0e1cf..64bb8a407 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -2,6 +2,7 @@ package edu.internet2.tier.shibboleth.admin.ui.util import edu.internet2.tier.shibboleth.admin.ui.domain.* import edu.internet2.tier.shibboleth.admin.ui.domain.filters.* +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget.EntityAttributesFilterTargetType import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterTargetRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation @@ -321,11 +322,23 @@ class TestObjectGenerator { return representation } + String buildEntityAttributesFilterTargetValueByType(EntityAttributesFilterTargetType type) { + switch (type) { + case EntityAttributesFilterTargetType.ENTITY: + return generator.randomString() + case EntityAttributesFilterTargetType.CONDITION_SCRIPT: + return "eval(true);" + case EntityAttributesFilterTargetType.REGEX: + return "/foo.*/" + } + } + EntityAttributesFilterTarget buildEntityAttributesFilterTarget() { EntityAttributesFilterTarget entityAttributesFilterTarget = new EntityAttributesFilterTarget() - entityAttributesFilterTarget.setSingleValue(generator.randomString()) entityAttributesFilterTarget.setEntityAttributesFilterTargetType(randomFilterTargetType()) + entityAttributesFilterTarget.setSingleValue( + buildEntityAttributesFilterTargetValueByType(entityAttributesFilterTarget.getEntityAttributesFilterTargetType())) return entityAttributesFilterTarget } @@ -353,8 +366,10 @@ class TestObjectGenerator { FilterTargetRepresentation buildFilterTargetRepresentation() { FilterTargetRepresentation representation = new FilterTargetRepresentation() - representation.setValue(generator.randomStringList()) representation.setType(randomFilterTargetType().toString()) + representation.setValue([ + buildEntityAttributesFilterTargetValueByType(representation.getType()) + ]) return representation } From dc3a20507e0574ab593753ea8a1f664ef185a38e Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 12 Sep 2018 12:54:39 -0700 Subject: [PATCH 28/56] [SHIBUI-570] Various test fixes. --- .../MetadataResolversControllerIntegrationTests.groovy | 4 ++-- .../tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index 221c5010e..69efa8133 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -7,12 +7,12 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFil import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import groovy.json.JsonOutput import groovy.json.JsonSlurper -import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest @@ -315,7 +315,7 @@ class MetadataResolversControllerIntegrationTests extends Specification { static class Config { @Bean MetadataResolver metadataResolver() { - new ChainingMetadataResolver() + new OpenSamlChainingMetadataResolver() } } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index 64bb8a407..13dc8a554 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -368,7 +368,7 @@ class TestObjectGenerator { representation.setType(randomFilterTargetType().toString()) representation.setValue([ - buildEntityAttributesFilterTargetValueByType(representation.getType()) + buildEntityAttributesFilterTargetValueByType(EntityAttributesFilterTargetType.valueOf(representation.getType())) ]) return representation From 712b143695b8ab850ffb24332224d0501b2603a1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 15:55:49 -0400 Subject: [PATCH 29/56] SHIBUI-836 --- ...penSamlFileBackedHTTPMetadataResolver.java | 8 ++--- ...SamlMetadataResolverConstructorHelper.java | 29 ++++++++++++------- .../MetadataResolverConverterServiceImpl.java | 11 +++++-- ...holderTokenAwareValueResolvingService.java | 2 +- ...TokenPlaceholderValueResolvingService.java | 2 +- ...aceholderValueResolvingServiceTests.groovy | 16 +++++----- .../admin/ui/util/TestObjectGenerator.groovy | 2 +- backend/src/test/resources/conf/278.2.xml | 2 +- backend/src/test/resources/conf/278.xml | 2 +- backend/src/test/resources/conf/532.xml | 2 +- 10 files changed, 43 insertions(+), 33 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 7327458eb..04c223bc0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -1,7 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver; -import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.resolver.ResolverException; import net.shibboleth.utilities.java.support.xml.ParserPool; @@ -40,11 +39,10 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes( this, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); - //TODO: complete resolving placeholders everywhere - //This might throw runtime exception if unable to resolve placeholders sent from higher layers - this.setBackupFile(placeholderResolverService().resolveValueFromTokenPlaceholder(sourceResolver.getBackingFile())); + this.setBackupFile(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackingFile())); this.setBackupFileInitNextRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()))); + .resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()))); this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile()); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java index 9d0383c11..d52e47448 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java @@ -3,7 +3,6 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicMetadataResolverAttributes; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes; -import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import net.shibboleth.utilities.java.support.xml.ParserPool; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractDynamicMetadataResolver; @@ -23,11 +22,14 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr AbstractDynamicMetadataResolver dynamicMetadataResolver = (AbstractDynamicMetadataResolver) metadataResolver; if (attributes.getBackgroundInitializationFromCacheDelay() != null) { - dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toMillis(attributes.getBackgroundInitializationFromCacheDelay())); + dynamicMetadataResolver + .setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } if (attributes.getCleanupTaskInterval() != null) { - dynamicMetadataResolver.setCleanupTaskInterval(toMillis(attributes.getCleanupTaskInterval())); + dynamicMetadataResolver.setCleanupTaskInterval(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getCleanupTaskInterval()))); } if (attributes.getInitializeFromPersistentCacheInBackground()) { @@ -35,19 +37,23 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr } if (attributes.getMaxCacheDuration() != null) { - dynamicMetadataResolver.setMaxCacheDuration(toMillis(attributes.getMaxCacheDuration())); + dynamicMetadataResolver.setMaxCacheDuration(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxCacheDuration()))); } if (attributes.getMaxIdleEntityData() != null) { - dynamicMetadataResolver.setMaxIdleEntityData(toMillis(attributes.getMaxIdleEntityData())); + dynamicMetadataResolver.setMaxIdleEntityData(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxIdleEntityData()))); } if (attributes.getMinCacheDuration() != null) { - dynamicMetadataResolver.setMinCacheDuration(toMillis(attributes.getMinCacheDuration())); + dynamicMetadataResolver.setMinCacheDuration(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getMinCacheDuration()))); } if (attributes.getBackgroundInitializationFromCacheDelay() != null) { - dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toMillis(attributes.getBackgroundInitializationFromCacheDelay())); + dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } if (attributes.getRefreshDelayFactor() != null) { @@ -87,18 +93,19 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA //TODO: This takes a ParserPool. We've got a ParserPoolRef in attributes.getParserPoolRef(). Should we use it for anything? reloadingMetadataResolver.setParserPool(parserPool); - //TODO: finish placeholder resolving if (attributes != null) { if (attributes.getExpirationWarningThreshold() != null) { reloadingMetadataResolver .setExpirationWarningThreshold(toMillis(placeholderResolverService() - .resolveValueFromTokenPlaceholder(attributes.getExpirationWarningThreshold()))); + .resolveValueFromPossibleTokenPlaceholder(attributes.getExpirationWarningThreshold()))); } if (attributes.getMaxRefreshDelay() != null) { - reloadingMetadataResolver.setMaxRefreshDelay(toMillis(attributes.getMaxRefreshDelay())); + reloadingMetadataResolver.setMaxRefreshDelay(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxRefreshDelay()))); } if (attributes.getMinRefreshDelay() != null) { - reloadingMetadataResolver.setMinRefreshDelay(toMillis(attributes.getMinRefreshDelay())); + reloadingMetadataResolver.setMinRefreshDelay(toMillis(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(attributes.getMinRefreshDelay()))); } if (attributes.getResolveViaPredicatesOnly() != null) { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java index 4ae0d07d2..b1147fa3d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java @@ -28,6 +28,8 @@ import java.io.IOException; import java.net.URL; +import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -60,7 +62,8 @@ private OpenSamlFileBackedHTTPMetadataResolver convertToOpenSamlRepresentation(F private OpenSamlFilesystemMetadataResolver convertToOpenSamlRepresentation(FilesystemMetadataResolver resolver) throws IOException, ResolverException, ComponentInitializationException { IndexWriter indexWriter = indexWriterService.getIndexWriter(resolver.getResourceId()); - URL url = Thread.currentThread().getContextClassLoader().getResource(resolver.getMetadataFile()); + URL url = Thread.currentThread().getContextClassLoader().getResource(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(resolver.getMetadataFile())); File metadataFile = new File(url.getPath()); OpenSamlFilesystemMetadataResolver openSamlResolver = new OpenSamlFilesystemMetadataResolver(openSamlObjects.getParserPool(), @@ -76,7 +79,8 @@ private OpenSamlLocalDynamicMetadataResolver convertToOpenSamlRepresentation(Loc XMLObjectLoadSaveManager manager = null; try { - manager = new FilesystemLoadSaveManager(resolver.getSourceDirectory()); + manager = new FilesystemLoadSaveManager(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(resolver.getSourceDirectory())); } catch (ConstraintViolationException e) { // the base directory string instance was null or empty //TODO: What should we do here? Currently, this causes a test to fail. @@ -96,7 +100,8 @@ private OpenSamlResourceBackedMetadataResolver convertToOpenSamlRepresentation(R //TODO: What sort of resource type should be created here? URL? break; case CLASSPATH: - resource = ResourceHelper.of(new ClassPathResource(resolver.getClasspathMetadataResource().getFile())); + resource = ResourceHelper.of(new ClassPathResource(placeholderResolverService() + .resolveValueFromPossibleTokenPlaceholder(resolver.getClasspathMetadataResource().getFile()))); break; default: throw new RuntimeException("Unsupported resource type!"); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 242027773..605abd540 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -28,7 +28,7 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok } @Override - public String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder) { + public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlaceholder) { //Ignore nulls. if(potentialTokenPlaceholder == null) { return potentialTokenPlaceholder; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java index 264ccc935..689ffbcbb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java @@ -10,7 +10,7 @@ @FunctionalInterface public interface TokenPlaceholderValueResolvingService { - String resolveValueFromTokenPlaceholder(String potentialTokenPlaceholder); + String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlaceholder); static TokenPlaceholderValueResolvingService shibbolethPlaceholderAware(PropertyResolver propertyResolver) { return new ShibbolethPlaceholderTokenAwareValueResolvingService(propertyResolver); diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy index 36837694c..8e3ba09f7 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingServiceTests.groovy @@ -33,8 +33,8 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { def "resolves correctly existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { when: 'Valid placeholder token is passed in for which property values are defined' - def idpHome = serviceUnderTest.resolveValueFromTokenPlaceholder('%{idp.home}') - def refreshInterval = serviceUnderTest.resolveValueFromTokenPlaceholder('%{refresh.interval}') + def idpHome = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder('%{idp.home}') + def refreshInterval = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder('%{refresh.interval}') then: 'Correct property value resolution is performed' idpHome == IDP_HOME @@ -43,15 +43,15 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { def "returns value as is if no well-formed shibboleth idp style placeholder tokens: %{} are passed in"() { when: 'Plain value without placeholder token is passed in' - def idpHome = serviceUnderTest.resolveValueFromTokenPlaceholder(IDP_HOME) - def plainValue = serviceUnderTest.resolveValueFromTokenPlaceholder(PLAIN_VALUE) + def idpHome = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder(IDP_HOME) + def plainValue = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder(PLAIN_VALUE) then: 'Value returned as is' idpHome == IDP_HOME plainValue == PLAIN_VALUE when: 'Malformed placeholder value is passed in' - plainValue = serviceUnderTest.resolveValueFromTokenPlaceholder('%{malformed.value') + plainValue = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder('%{malformed.value') then: plainValue == '%{malformed.value' @@ -59,13 +59,13 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { def "Throws IllegalArgumentException for unresolvable properties"() { when: 'Valid placeholder token is passed in for which property values are undefined' - serviceUnderTest.resolveValueFromTokenPlaceholder("%{i.am.not.defined}") + serviceUnderTest.resolveValueFromPossibleTokenPlaceholder("%{i.am.not.defined}") then: thrown IllegalArgumentException when: 'Combination of resolvable and unresolvable tokens are passed in' - serviceUnderTest.resolveValueFromTokenPlaceholder("%{idp.home}/%{i.am.not.defined}") + serviceUnderTest.resolveValueFromPossibleTokenPlaceholder("%{idp.home}/%{i.am.not.defined}") then: thrown IllegalArgumentException @@ -73,7 +73,7 @@ class TokenPlaceholderValueResolvingServiceTests extends Specification { def "resolves correctly combination of existing properties from well-formed shibboleth idp style placeholder tokens: %{}"() { when: 'Valid placeholder token is passed in for which property values are defined' - def combinedValue = serviceUnderTest.resolveValueFromTokenPlaceholder('%{idp.home} AND %{refresh.interval}') + def combinedValue = serviceUnderTest.resolveValueFromPossibleTokenPlaceholder('%{idp.home} AND %{refresh.interval}') then: 'Correct combined property values resolution is performed' combinedValue == "$IDP_HOME AND $REFRESH_INTERVAL" diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index 7510f9929..3faa17cdf 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -456,7 +456,7 @@ class TestObjectGenerator { new FileBackedHttpMetadataResolver().with { it.name = 'HTTPMetadata' it.xmlId = 'HTTPMetadata' - it.backingFile = 'unicon.xml' + it.backingFile = '%{idp.home}/metadata/metadata.xml' it.metadataURL = 'https://idp.unicon.net/idp/shibboleth' it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { diff --git a/backend/src/test/resources/conf/278.2.xml b/backend/src/test/resources/conf/278.2.xml index 2b71b5ed1..a7adef87f 100644 --- a/backend/src/test/resources/conf/278.2.xml +++ b/backend/src/test/resources/conf/278.2.xml @@ -38,7 +38,7 @@ Date: Wed, 12 Sep 2018 16:00:24 -0400 Subject: [PATCH 30/56] SHIBUI-836: polishing --- .../tier/shibboleth/admin/util/TokenPlaceholderResolvers.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java index f65737be2..8c8b2898d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java @@ -1,8 +1,6 @@ package edu.internet2.tier.shibboleth.admin.util; import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; public class TokenPlaceholderResolvers { From 9d4b637432a1d7638fdeb7b0c8a766053b4d27c1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:01:42 -0400 Subject: [PATCH 31/56] SHIBUI-836: polishing --- .../ShibbolethPlaceholderTokenAwareValueResolvingService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 605abd540..14725f4fd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -2,9 +2,6 @@ import org.springframework.core.env.PropertyResolver; -import java.util.Objects; - -import static java.util.Objects.requireNonNull; /** * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's default property resolver From 1697c705a67e570389995b19b7deda6fbd203e9c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:02:14 -0400 Subject: [PATCH 32/56] SHIBUI-836: polishing --- .../ShibbolethPlaceholderTokenAwareValueResolvingService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 14725f4fd..9ba4d8e82 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -8,7 +8,7 @@ * which understands and replaces Shibboleth Idp specific placeholder prefix of '%{' with standard Spring's placeholder * prefix of '${' before resolving. * - * If passed it value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. + * If passed in value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. * * @author Dmitriy Kopylenko */ From 4c536047e091e64eb455a7f87a3c10cf5aca0285 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:03:29 -0400 Subject: [PATCH 33/56] SHIBUI-836: polishing --- ...hibbolethPlaceholderTokenAwareValueResolvingService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 9ba4d8e82..e869c626f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -18,7 +18,7 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok private static final String SHIB_IDP_PLACEHOLDER_PREEFIX = "%{"; - private static final String STANDART_PLACEHOLDER_PREFIX = "${"; + private static final String STANDARD_PLACEHOLDER_PREFIX = "${"; ShibbolethPlaceholderTokenAwareValueResolvingService(PropertyResolver propertyResolver) { this.propertyResolver = propertyResolver; @@ -33,7 +33,7 @@ public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlac if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREEFIX)) { String normalizedTokenPlaceholder = - potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREEFIX, STANDART_PLACEHOLDER_PREFIX); + potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREEFIX, STANDARD_PLACEHOLDER_PREFIX); //This call might result in IllegalArgumentException if it's unable to resolve passed in property(ies) //e.g. due to bad data sent, etc. This is OK, as passing correct data and ensuring that //property values are correctly set is the responsibility of the software operator @@ -42,7 +42,7 @@ public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlac //Indicates that malformed values such as %{incomplete.token are passed. Spring won't resolve and return //the value as is. Just change it back to the original shib-style token and return. if(resolved.equals(normalizedTokenPlaceholder)) { - return resolved.replace(STANDART_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREEFIX); + return resolved.replace(STANDARD_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREEFIX); } return resolved; } From 1136a01df6e41ac3392f44407feeae1055ba200c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:03:52 -0400 Subject: [PATCH 34/56] SHIBUI-836: polishing --- ...bbolethPlaceholderTokenAwareValueResolvingService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index e869c626f..52ca767f0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -16,7 +16,7 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok private PropertyResolver propertyResolver; - private static final String SHIB_IDP_PLACEHOLDER_PREEFIX = "%{"; + private static final String SHIB_IDP_PLACEHOLDER_PREFIX = "%{"; private static final String STANDARD_PLACEHOLDER_PREFIX = "${"; @@ -31,9 +31,9 @@ public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlac return potentialTokenPlaceholder; } - if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREEFIX)) { + if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREFIX)) { String normalizedTokenPlaceholder = - potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREEFIX, STANDARD_PLACEHOLDER_PREFIX); + potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREFIX, STANDARD_PLACEHOLDER_PREFIX); //This call might result in IllegalArgumentException if it's unable to resolve passed in property(ies) //e.g. due to bad data sent, etc. This is OK, as passing correct data and ensuring that //property values are correctly set is the responsibility of the software operator @@ -42,7 +42,7 @@ public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlac //Indicates that malformed values such as %{incomplete.token are passed. Spring won't resolve and return //the value as is. Just change it back to the original shib-style token and return. if(resolved.equals(normalizedTokenPlaceholder)) { - return resolved.replace(STANDARD_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREEFIX); + return resolved.replace(STANDARD_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREFIX); } return resolved; } From 6d84f57778f732461c44f737854148905e5239b3 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 12 Sep 2018 13:14:03 -0700 Subject: [PATCH 35/56] [SHIBUI-570] Replaced a println. --- .../admin/ui/service/JPAMetadataResolverServiceImpl.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ec201d00b..f8eb32a38 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 @@ -96,7 +96,7 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { (Refilterable) targetMetadataResolver.refilter() } else { //TODO: Do something here if we need to refilter other non-Batch resolvers - println("We shouldn't be here. But we are. Why?") + log.warn("Target resolver is not a Refilterable resolver. Skipping refilter()") } } From 7c3b9347bbddcc3b3fc20257cbd67dc7cc0acaa1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:16:33 -0400 Subject: [PATCH 36/56] SHIBUI-836: polishing --- .../IdpHomeValueSettingEnvironmentPostProcessor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java index 814a797c2..97eb0bd4f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java @@ -17,9 +17,11 @@ import java.util.Map; /** - * Spring Boot Environment Post Processor setting the value for idp.home property to an abstract temp directory + * Spring Boot Environment Post Processor setting the value for idp.home property to a temp directory * if no IDP_HOME environment variable has been set already. * + * Also creates IDP_HOME/metadata directory if no such directory already exixst. + * * @author Dmitriy Kopylenko */ public class IdpHomeValueSettingEnvironmentPostProcessor implements EnvironmentPostProcessor { From 347da0d13927d20d650096e7e7b16078167aac19 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Sep 2018 16:23:52 -0400 Subject: [PATCH 37/56] SHIBUI-836: typo --- .../IdpHomeValueSettingEnvironmentPostProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java index 97eb0bd4f..7474af1f5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java @@ -20,7 +20,7 @@ * Spring Boot Environment Post Processor setting the value for idp.home property to a temp directory * if no IDP_HOME environment variable has been set already. * - * Also creates IDP_HOME/metadata directory if no such directory already exixst. + * Also creates IDP_HOME/metadata directory if no such directory already exists. * * @author Dmitriy Kopylenko */ From 3620e0afe6fb63afcbb76bc94e5e583b13003b53 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Sep 2018 11:03:21 -0400 Subject: [PATCH 38/56] SHIBUI-836: fix test --- .../shibboleth/admin/ui/domain/EntityDescriptorTest.groovy | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptorTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptorTest.groovy index 79a539086..5fe53b85b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptorTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptorTest.groovy @@ -2,6 +2,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes @@ -18,6 +19,7 @@ import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean import org.springframework.data.jpa.repository.config.EnableJpaRepositories @@ -31,7 +33,7 @@ import java.nio.file.Files * @author Bill Smith (wsmith@unicon.net) */ @DataJpaTest -@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, InternationalizationConfiguration, MyConfig]) +@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, InternationalizationConfiguration, MyConfig, PlaceholderResolverComponentsConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @@ -58,14 +60,13 @@ class EntityDescriptorTest extends Specification { def "entity descriptors properly marshall to xml"() { given: - def tempDir = Files.createTempDirectory('test') ((OpenSamlChainingMetadataResolver)metadataResolver).resolvers = [ new OpenSamlFileBackedHTTPMetadataResolver( openSamlObjects.parserPool, indexWriterService.getIndexWriter('testme'), new FileBackedHttpMetadataResolver( metadataURL: 'https://idp.unicon.net/idp/shibboleth', - backingFile: "${tempDir.toString()}/test.xml", + backingFile: "%{idp.home}/metadata/test.xml", reloadableMetadataResolverAttributes: new ReloadableMetadataResolverAttributes(), httpMetadataResolverAttributes: new HttpMetadataResolverAttributes() ) From 0b1800f24810e5010d39d9e9d05fcd283eb2440f Mon Sep 17 00:00:00 2001 From: Jj! Date: Thu, 13 Sep 2018 11:30:24 -0500 Subject: [PATCH 39/56] [SHIBUI-794] WIP --- Jenkinsfile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..596c3147d --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,19 @@ +pipeline { + agent any + options { + disableConcurrentBuilds() + buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10')) + } + stages { + stage('Build') { + steps { + sh './gradlew clean build' + } + post { + always { + junit 'backend/build/test-results/**/*.xml' + } + } + } + } +} \ No newline at end of file From f15646f0cc695d444f58abf4d42332a163c1ea7f Mon Sep 17 00:00:00 2001 From: Jj! Date: Thu, 13 Sep 2018 11:56:47 -0500 Subject: [PATCH 40/56] [SHIBUI-794] WIP --- Jenkinsfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Jenkinsfile b/Jenkinsfile index 596c3147d..531037dc0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -12,6 +12,7 @@ pipeline { post { always { junit 'backend/build/test-results/**/*.xml' + jacoco execPattern: '**/build/jacoco/test.exec' } } } From 7928889fbc1ecacd4a5fc09d64e058dcefa26d9d Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 12:02:03 -0500 Subject: [PATCH 41/56] [SHIBUI-794] WIP --- Jenkinsfile | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index 531037dc0..1fec50052 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -16,5 +16,36 @@ pipeline { } } } + stage('Build Docker images') { + when { + expression { + return GIT_BRANCH in ['master', 'SHIBUI-794'] + } + } + steps { + sh '''./gradlew docker + ''' + } + } + stage('Deploy') { + when { + expression { + return GIT_BRANCH in ['master', 'SHIBUI-794'] + } + } + steps { + sh ''' + docker run unicon/shibui + ''' + } + } + } + post { + failure { + step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']])]) + } + success { + emailext body: '''${SCRIPT, template="groovy-text.template"}''', recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], subject: '[SHIBUI] Build Success' + } } } \ No newline at end of file From e0048b35e9cefd53cba1c026a983c0922a7e35d2 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 12:59:51 -0500 Subject: [PATCH 42/56] [SHIBUI-794] WIP --- .../MetadataResolversControllerIntegrationTests.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index 69efa8133..59d24409e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -178,7 +178,8 @@ class MetadataResolversControllerIntegrationTests extends Specification { where: resolverType | _ 'DynamicHttp' | _ - 'FileBacked' | _ + // TODO: fix + // 'FileBacked' | _ 'LocalDynamic' | _ 'ResourceBacked' | _ 'Filesystem' | _ From d341ab134d7fe8f02ab5ea220f21366b1e091d1c Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 13:12:03 -0500 Subject: [PATCH 43/56] [SHIBUI-794] WIP --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1fec50052..1c3657f47 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -35,7 +35,7 @@ pipeline { } steps { sh ''' - docker run unicon/shibui + docker run -d --restart unicon/shibui ''' } } From 2b3340d6cfc36ed8f7d07c6dc1899510a337b4a8 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 13:23:34 -0500 Subject: [PATCH 44/56] [SHIBUI-794] WIP --- Jenkinsfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 1c3657f47..33ea8a208 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -34,8 +34,7 @@ pipeline { } } steps { - sh ''' - docker run -d --restart unicon/shibui + sh '''docker run -d --restart unicon/shibui ''' } } From 70179903a15c38738c60a2c68d07fec5344d70d9 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 13:25:47 -0500 Subject: [PATCH 45/56] [SHIBUI-794] WIP --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 33ea8a208..86cb0bc33 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -34,7 +34,7 @@ pipeline { } } steps { - sh '''docker run -d --restart unicon/shibui + sh '''docker run -d --restart always unicon/shibui ''' } } From 8fa65d0eb4f127daa3e05a98fcb5e8de1eed0106 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 13:32:14 -0500 Subject: [PATCH 46/56] [SHIBUI-794] WIP --- .../MetadataResolversControllerIntegrationTests.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index 59d24409e..e9c7bac13 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -227,7 +227,8 @@ class MetadataResolversControllerIntegrationTests extends Specification { where: resolverType | _ 'DynamicHttp' | _ - 'FileBacked' | _ + // TODO: fix + // 'FileBacked' | _ 'LocalDynamic' | _ 'ResourceBacked' | _ 'Filesystem' | _ From 0d45c53731e836929f12cbc16c532338f7107488 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 13:56:14 -0500 Subject: [PATCH 47/56] [SHIBUI-794] WIP --- Jenkinsfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 86cb0bc33..eb6e72ef4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -34,7 +34,9 @@ pipeline { } } steps { - sh '''docker run -d --restart always unicon/shibui + sh ''' + docker stop shibui + docker run -d --restart always -t shibui unicon/shibui --spring.config.location=file:/etc/shibui ''' } } From 5058f48527d1274d0b5973d5b9a22184bfe51367 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 14:18:31 -0500 Subject: [PATCH 48/56] [SHIBUI-794] WIP --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index eb6e72ef4..e1eaa66f9 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -35,8 +35,8 @@ pipeline { } steps { sh ''' - docker stop shibui - docker run -d --restart always -t shibui unicon/shibui --spring.config.location=file:/etc/shibui + docker stop shibui || true + docker run -d --restart always -t shibui -p 8080:8080 unicon/shibui --spring.config.location=file:/etc/shibui ''' } } From 342ca41f0e9c3cff1b7c7e7ce90c65e646fc8936 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 14:47:14 -0500 Subject: [PATCH 49/56] [SHIBUI-794] WIP --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index e1eaa66f9..29089222d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,7 +36,7 @@ pipeline { steps { sh ''' docker stop shibui || true - docker run -d --restart always -t shibui -p 8080:8080 unicon/shibui --spring.config.location=file:/etc/shibui + docker run -d --restart always -t shibui -p 8080:8080 unicon/shibui:latest --spring.config.location=file:/etc/shibui ''' } } From f5646849e6fb4476e8e376ca8d728d8930d9c4a5 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 14:53:27 -0500 Subject: [PATCH 50/56] [SHIBUI-794] WIP --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 29089222d..12179561c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -35,8 +35,8 @@ pipeline { } steps { sh ''' - docker stop shibui || true - docker run -d --restart always -t shibui -p 8080:8080 unicon/shibui:latest --spring.config.location=file:/etc/shibui + docker stop shibui || true && docker rm shibui || true + docker run -d --restart always --name shibui -p 8080:8080 unicon/shibui:latest --spring.config.location=file:/etc/shibui ''' } } From 927bf45b07ad9057b0445d91c3d01e6031c6f980 Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 15:06:14 -0500 Subject: [PATCH 51/56] [SHIBUI-794] WIP --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 12179561c..3d72e20ba 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,7 +36,7 @@ pipeline { steps { sh ''' docker stop shibui || true && docker rm shibui || true - docker run -d --restart always --name shibui -p 8080:8080 unicon/shibui:latest --spring.config.location=file:/etc/shibui + docker run -d --restart always --name shibui -p 8080:8080 -v /etc/shibui/application.properties:/application.properties unicon/shibui:latest ''' } } From 17fc2f2072f4ee07eb3f9fe1ccf0c4872dba1daf Mon Sep 17 00:00:00 2001 From: Jj! Date: Fri, 14 Sep 2018 15:40:21 -0500 Subject: [PATCH 52/56] [SHIBUI-794] WIP --- .../MetadataResolversControllerIntegrationTests.groovy | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index e9c7bac13..69efa8133 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -178,8 +178,7 @@ class MetadataResolversControllerIntegrationTests extends Specification { where: resolverType | _ 'DynamicHttp' | _ - // TODO: fix - // 'FileBacked' | _ + 'FileBacked' | _ 'LocalDynamic' | _ 'ResourceBacked' | _ 'Filesystem' | _ @@ -227,8 +226,7 @@ class MetadataResolversControllerIntegrationTests extends Specification { where: resolverType | _ 'DynamicHttp' | _ - // TODO: fix - // 'FileBacked' | _ + 'FileBacked' | _ 'LocalDynamic' | _ 'ResourceBacked' | _ 'Filesystem' | _ From 3359872babbcc1dd35e3647a610b4d250fffa8e4 Mon Sep 17 00:00:00 2001 From: Jj! Date: Mon, 17 Sep 2018 09:29:48 -0500 Subject: [PATCH 53/56] [SHIBUI-794] cleanup --- Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 3d72e20ba..73ca4bfdf 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -19,7 +19,7 @@ pipeline { stage('Build Docker images') { when { expression { - return GIT_BRANCH in ['master', 'SHIBUI-794'] + return GIT_BRANCH in ['master'] } } steps { @@ -30,7 +30,7 @@ pipeline { stage('Deploy') { when { expression { - return GIT_BRANCH in ['master', 'SHIBUI-794'] + return GIT_BRANCH in ['master'] } } steps { From 1d24a1d64cd18f89cd43bc5dbc27e9dc911a3060 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 18 Sep 2018 10:30:37 -0400 Subject: [PATCH 54/56] SHIBUI-836: Refactor based on code review --- ...holderResolverComponentsConfiguration.java | 6 +-- ...eValueSettingEnvironmentPostProcessor.java | 41 ++++++----------- ...holderTokenAwareValueResolvingService.java | 45 +++++-------------- ...TokenPlaceholderValueResolvingService.java | 6 ++- .../admin/util/TokenPlaceholderResolvers.java | 5 +++ 5 files changed, 37 insertions(+), 66 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java index 484675e3d..bd391e0d5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/PlaceholderResolverComponentsConfiguration.java @@ -4,14 +4,14 @@ import edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.PropertyResolver; +import org.springframework.core.env.ConfigurableEnvironment; @Configuration public class PlaceholderResolverComponentsConfiguration { @Bean - public TokenPlaceholderValueResolvingService tokenPlaceholderValueResolvingService(PropertyResolver propertyResolver) { - return TokenPlaceholderValueResolvingService.shibbolethPlaceholderAware(propertyResolver); + public TokenPlaceholderValueResolvingService tokenPlaceholderValueResolvingService(ConfigurableEnvironment env) { + return TokenPlaceholderValueResolvingService.shibbolethPlaceholderPrefixAware(env.getPropertySources()); } @Bean diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java index 7474af1f5..8f8bd3499 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/postprocessors/IdpHomeValueSettingEnvironmentPostProcessor.java @@ -1,6 +1,5 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration.postprocessors; -import lombok.extern.log4j.Log4j2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.SpringApplication; @@ -8,7 +7,6 @@ import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -20,8 +18,6 @@ * Spring Boot Environment Post Processor setting the value for idp.home property to a temp directory * if no IDP_HOME environment variable has been set already. * - * Also creates IDP_HOME/metadata directory if no such directory already exists. - * * @author Dmitriy Kopylenko */ public class IdpHomeValueSettingEnvironmentPostProcessor implements EnvironmentPostProcessor { @@ -34,31 +30,20 @@ public class IdpHomeValueSettingEnvironmentPostProcessor implements EnvironmentP @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { - String existingIdpHome = environment.getProperty(IDP_HOME_PROP); - Path metadataSubDir = Paths.get(existingIdpHome, METADATA_DIR); - if (existingIdpHome != null) { - if (!Files.exists(metadataSubDir)) { - try { - Files.createDirectories(metadataSubDir); - } catch (IOException e) { - LOGGER.error(e.getMessage()); - throw new RuntimeException(e); - } + if(environment.getProperty(IDP_HOME_PROP) == null) { + Map map = new HashMap<>(1); + try { + Path tempDir = Files.createTempDirectory(null); + tempDir.toFile().deleteOnExit(); + String tempDirName = tempDir.toAbsolutePath().toString(); + Path tempMetadataSubDir = Paths.get(tempDirName, METADATA_DIR); + Files.createDirectories(tempMetadataSubDir); + map.put(IDP_HOME_PROP, tempDirName); + } catch (IOException e) { + LOGGER.error(e.getMessage()); + throw new RuntimeException(e); } - return; - } - - Map map = new HashMap<>(1); - try { - Path tempDir = Files.createTempDirectory(String.format("%s.%s.", "shibui", IDP_HOME_PROP)); - String tempDirName = tempDir.toAbsolutePath().toString(); - Path tempMetadataSubDir = Paths.get(tempDirName, METADATA_DIR); - Files.createDirectories(tempMetadataSubDir); - map.put(IDP_HOME_PROP, tempDirName); - } catch (IOException e) { - LOGGER.error(e.getMessage()); - throw new RuntimeException(e); + environment.getPropertySources().addLast(new MapPropertySource("idp.home.propertysource", map)); } - environment.getPropertySources().addLast(new MapPropertySource("idp.home.propertysource", map)); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java index 52ca767f0..5ae9a60cc 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibbolethPlaceholderTokenAwareValueResolvingService.java @@ -1,14 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import org.springframework.core.env.PropertyResolver; +import org.springframework.core.env.PropertySources; +import org.springframework.core.env.PropertySourcesPropertyResolver; /** - * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's default property resolver - * which understands and replaces Shibboleth Idp specific placeholder prefix of '%{' with standard Spring's placeholder - * prefix of '${' before resolving. - * - * If passed in value does not contain Shibboleth Idp '%{}' placeholder token, returns that value as is. + * Implementation of {@link TokenPlaceholderValueResolvingService} based on Spring Framework's property resolver which + * understands Shibboleth Idp custom placeholder prefix of %{ and can resolve property values from these + * placeholders against existing property sources. * * @author Dmitriy Kopylenko */ @@ -16,37 +16,16 @@ public class ShibbolethPlaceholderTokenAwareValueResolvingService implements Tok private PropertyResolver propertyResolver; - private static final String SHIB_IDP_PLACEHOLDER_PREFIX = "%{"; - - private static final String STANDARD_PLACEHOLDER_PREFIX = "${"; - - ShibbolethPlaceholderTokenAwareValueResolvingService(PropertyResolver propertyResolver) { - this.propertyResolver = propertyResolver; + ShibbolethPlaceholderTokenAwareValueResolvingService(PropertySources propertySources) { + PropertySourcesPropertyResolver propertySourcesPropertyResolver = new PropertySourcesPropertyResolver(propertySources); + propertySourcesPropertyResolver.setPlaceholderPrefix("%{"); + this.propertyResolver = propertySourcesPropertyResolver; } @Override public String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlaceholder) { - //Ignore nulls. - if(potentialTokenPlaceholder == null) { - return potentialTokenPlaceholder; - } - - if(potentialTokenPlaceholder.contains(SHIB_IDP_PLACEHOLDER_PREFIX)) { - String normalizedTokenPlaceholder = - potentialTokenPlaceholder.replace(SHIB_IDP_PLACEHOLDER_PREFIX, STANDARD_PLACEHOLDER_PREFIX); - //This call might result in IllegalArgumentException if it's unable to resolve passed in property(ies) - //e.g. due to bad data sent, etc. This is OK, as passing correct data and ensuring that - //property values are correctly set is the responsibility of the software operator - String resolved = this.propertyResolver.resolveRequiredPlaceholders(normalizedTokenPlaceholder); - - //Indicates that malformed values such as %{incomplete.token are passed. Spring won't resolve and return - //the value as is. Just change it back to the original shib-style token and return. - if(resolved.equals(normalizedTokenPlaceholder)) { - return resolved.replace(STANDARD_PLACEHOLDER_PREFIX, SHIB_IDP_PLACEHOLDER_PREFIX); - } - return resolved; - } - //No token placeholders, just return the given data as is - return potentialTokenPlaceholder; + return potentialTokenPlaceholder != null + ? this.propertyResolver.resolveRequiredPlaceholders(potentialTokenPlaceholder) + : potentialTokenPlaceholder; } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java index 689ffbcbb..19d8217ff 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/TokenPlaceholderValueResolvingService.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import org.springframework.core.env.PropertyResolver; +import org.springframework.core.env.PropertySources; /** * Generic API to resolve values from arbitrary tokenized placeholders such as '%{token.placeholder}' etc. @@ -12,7 +13,8 @@ public interface TokenPlaceholderValueResolvingService { String resolveValueFromPossibleTokenPlaceholder(String potentialTokenPlaceholder); - static TokenPlaceholderValueResolvingService shibbolethPlaceholderAware(PropertyResolver propertyResolver) { - return new ShibbolethPlaceholderTokenAwareValueResolvingService(propertyResolver); + + static TokenPlaceholderValueResolvingService shibbolethPlaceholderPrefixAware(PropertySources propertySources) { + return new ShibbolethPlaceholderTokenAwareValueResolvingService(propertySources); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java index 8c8b2898d..9ac8947b7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/TokenPlaceholderResolvers.java @@ -2,6 +2,11 @@ import edu.internet2.tier.shibboleth.admin.ui.service.TokenPlaceholderValueResolvingService; +/** + * Accessor facade class to expose {@link TokenPlaceholderValueResolvingService} to non-Spring-managed classes. + * + * @author Dmitriy Kopylenko + */ public class TokenPlaceholderResolvers { private static TokenPlaceholderValueResolvingService placeholderResolverService; From c62384f4abd3cbcdf80ece98fc1def3e909f625f Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 19 Sep 2018 12:22:53 -0700 Subject: [PATCH 55/56] [SHIBUI-839] Added a StringTrimModule that trims all leading and trailing whitespace from Strings as Jackson deserializes them. --- .../CoreShibUiConfiguration.java | 6 +++++ .../ui/configuration/StringTrimModule.java | 26 +++++++++++++++++++ ...ResolversControllerIntegrationTests.groovy | 16 +++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StringTrimModule.java 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 c9b6493fa..e17c33b0e 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 @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; +import com.fasterxml.jackson.databind.Module; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; @@ -168,4 +169,9 @@ public DirectoryService directoryService() { public LuceneUtility luceneUtility(DirectoryService directoryService) { return new LuceneUtility(directoryService); } + + @Bean + public Module stringTrimModule() { + return new StringTrimModule(); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StringTrimModule.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StringTrimModule.java new file mode 100644 index 000000000..8c04ab071 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StringTrimModule.java @@ -0,0 +1,26 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer; +import com.fasterxml.jackson.databind.module.SimpleModule; + +import java.io.IOException; + +/** + * @author Bill Smith (wsmith@unicon.net) + * + * Adapted from Maciej Marczuk's answer on Stack Overflow here: + * https://stackoverflow.com/questions/6852213/can-jackson-be-configured-to-trim-leading-trailing-whitespace-from-all-string-pr/33765854#33765854 + */ +public class StringTrimModule extends SimpleModule { + + public StringTrimModule() { + addDeserializer(String.class, new StdScalarDeserializer(String.class) { + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException { + return jsonParser.getValueAsString().trim(); + } + }); + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index 69efa8133..f12e6b8ef 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -150,13 +150,27 @@ class MetadataResolversControllerIntegrationTests extends Specification { result.statusCodeValue == 404 } + @DirtiesContext + def "SHIBUI-839 - POST resolver with spaces in the provider name results in trimmed name"() { + given: + def resolver = generator.buildRandomMetadataResolverOfType('DynamicHttp') + resolver.name = ' This name has spaces ' + + when: + def result = this.restTemplate.postForEntity(BASE_URI, createRequestHttpEntityFor { mapper.writeValueAsString(resolver) }, String) + + then: + def metadataResolverMap = new JsonSlurper().parseText(result.body) + metadataResolverMap.name == resolver.name.trim() + } + @Unroll @DirtiesContext def "POST new concrete MetadataResolver of type #resolverType -> /api/MetadataResolvers"(String resolverType) { given: 'New MetadataResolver JSON representation' def resolver = generator.buildRandomMetadataResolverOfType(resolverType) String sourceDirectory - if (resolverType.equals('Localdynamic')) { + if (resolverType.equals('LocalDynamic')) { sourceDirectory = ((LocalDynamicMetadataResolver) resolver).sourceDirectory } From 35a1f0b2ffdc20a49e3edbc8cf3c8ae877f86ef2 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Thu, 20 Sep 2018 09:51:56 -0700 Subject: [PATCH 56/56] [SHIBUI-839] Updated test to not use String.trim(). --- .../MetadataResolversControllerIntegrationTests.groovy | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index f12e6b8ef..c4453305f 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -155,13 +155,14 @@ class MetadataResolversControllerIntegrationTests extends Specification { given: def resolver = generator.buildRandomMetadataResolverOfType('DynamicHttp') resolver.name = ' This name has spaces ' + def expectedName = 'This name has spaces' when: def result = this.restTemplate.postForEntity(BASE_URI, createRequestHttpEntityFor { mapper.writeValueAsString(resolver) }, String) then: def metadataResolverMap = new JsonSlurper().parseText(result.body) - metadataResolverMap.name == resolver.name.trim() + metadataResolverMap.name == expectedName } @Unroll