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 @@