[java-identity-provider] branch master updated: Add inline/resource scripting to EntityAttributes metadata filter.
Scott Cantor
cantor.2 at osu.edu
Tue May 9 14:15:28 EDT 2017
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=77901b29910394cfa185ca3e598c958bc97a36c1
The following commit(s) were added to refs/heads/master by this push:
new 77901b2 Add inline/resource scripting to EntityAttributes metadata filter.
77901b2 is described below
commit 77901b29910394cfa185ca3e598c958bc97a36c1
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue May 9 14:15:14 2017 -0400
Add inline/resource scripting to EntityAttributes metadata filter.
---
.../metadata/ScriptTypeBeanParser.java | 84 ++++++++++++++
.../filter/impl/EntityAttributesFilterParser.java | 29 ++++-
.../metadata/AbstractMetadataParserTest.java | 6 +-
.../filter/EntityAttributesFilterParserTest.java | 18 ++-
.../metadata/filter/entityAttributes.xml | 3 +-
.../entityAttributesAttributeFilterScript.js | 2 +
.../filter/entityAttributesConditionScript.js | 2 +
...tributes.xml => entityAttributesWithScript.xml} | 9 +-
....xml => entityAttributesWithScriptResource.xml} | 9 +-
.../main/resources/schema/shibboleth-metadata.xsd | 124 +++++++++++++++------
10 files changed, 238 insertions(+), 48 deletions(-)
diff --git a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/ScriptTypeBeanParser.java b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/ScriptTypeBeanParser.java
new file mode 100644
index 0000000..42963e3
--- /dev/null
+++ b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/ScriptTypeBeanParser.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.spring.relyingparty.metadata;
+
+
+import javax.annotation.Nonnull;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.w3c.dom.Element;
+
+/**
+ * Parser for elements derived from ScriptType in the <code>urn:mace:shibboleth:2.0:metadata</code> namespace.
+ *
+ * <p>The actual bean type is a runtime class so that different objects adhering to the general factory
+ * contracts used with scripted beans will work.</p>
+ */
+public final class ScriptTypeBeanParser {
+
+ /** Namespace for Metadata. */
+ @Nonnull @NotEmpty public static final String METADATA_NAMESPACE = "urn:mace:shibboleth:2.0:metadata";
+
+ /** Logger. */
+ @Nonnull private static final Logger LOG = LoggerFactory.getLogger(ScriptTypeBeanParser.class);
+
+ /** Private c'tor. */
+ private ScriptTypeBeanParser() {
+
+ }
+
+ /**
+ * Parse and return a builder for a bean adhering to the contract of ScriptedType.
+ *
+ * @param type type of object to build
+ * @param element root of XML configuration
+ *
+ * @return bean definition builder
+ */
+ @Nonnull public static BeanDefinitionBuilder parseScriptType(@Nonnull final Class type,
+ @Nonnull final Element element) {
+
+ final BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(type);
+
+ if (element.hasAttributeNS(null, "language")) {
+ final String scriptLanguage = StringSupport.trimOrNull(element.getAttributeNS(null, "language"));
+ builder.addConstructorArgValue(scriptLanguage);
+ }
+ final String customRef = StringSupport.trimOrNull(element.getAttributeNS(null, "customObjectRef"));
+ if (null != customRef) {
+ builder.addPropertyReference("customObject", customRef);
+ }
+ final Element scriptChild = ElementSupport.getFirstChildElement(element);
+ builder.addConstructorArgValue(ElementSupport.getElementContentAsString(scriptChild));
+ if (ElementSupport.isElementNamed(scriptChild, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+ "Script")) {
+ builder.setFactoryMethod("inlineScript");
+ } else if (ElementSupport.isElementNamed(scriptChild, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+ "ScriptFile")) {
+ builder.setFactoryMethod("resourceScript");
+ }
+
+ return builder;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/impl/EntityAttributesFilterParser.java b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/impl/EntityAttributesFilterParser.java
index 570bb13..d99fe72 100644
--- a/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/impl/EntityAttributesFilterParser.java
+++ b/idp-profile-spring/src/main/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/impl/EntityAttributesFilterParser.java
@@ -24,7 +24,8 @@ import javax.annotation.Nonnull;
import javax.xml.namespace.QName;
import net.shibboleth.idp.profile.spring.relyingparty.metadata.AbstractMetadataProviderParser;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.idp.profile.spring.relyingparty.metadata.ScriptTypeBeanParser;
+import net.shibboleth.utilities.java.support.logic.ScriptedPredicate;
import net.shibboleth.utilities.java.support.xml.ElementSupport;
import org.opensaml.core.xml.XMLObject;
@@ -60,6 +61,7 @@ public class EntityAttributesFilterParser extends AbstractSingleBeanDefinitionPa
return EntityAttributesFilter.class;
}
+// Checkstyle: CyclomaticComplexity OFF
/** {@inheritDoc} */
@Override protected void doParse(final Element element, final ParserContext parserContext,
final BeanDefinitionBuilder builder) {
@@ -75,6 +77,19 @@ public class EntityAttributesFilterParser extends AbstractSingleBeanDefinitionPa
final ManagedMap<Object, ManagedList<Attribute>> ruleMap = new ManagedMap();
Element child = ElementSupport.getFirstChildElement(element);
+
+ // Check for Predicate at the top.
+ if (ElementSupport.isElementNamed(child, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+ "AttributeFilterRef")) {
+ builder.addPropertyReference("attributeFilter", ElementSupport.getElementContentAsString(child));
+ child = ElementSupport.getNextSiblingElement(child);
+ } else if (ElementSupport.isElementNamed(child, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+ "AttributeFilterScript")) {
+ builder.addPropertyValue("attributeFilter",
+ ScriptTypeBeanParser.parseScriptType(ScriptedPredicate.class, child).getBeanDefinition());
+ }
+
+ // Loop over remaining children.
while (child != null) {
if (ElementSupport.isElementNamed(child, Attribute.DEFAULT_ELEMENT_NAME)) {
try {
@@ -98,17 +113,19 @@ public class EntityAttributesFilterParser extends AbstractSingleBeanDefinitionPa
final ManagedList<Attribute> forRule = new ManagedList(accumulator.size());
forRule.addAll(accumulator);
ruleMap.put(new RuntimeBeanReference(ElementSupport.getElementContentAsString(child)), forRule);
+ } else if (ElementSupport.isElementNamed(child, AbstractMetadataProviderParser.METADATA_NAMESPACE,
+ "ConditionScript")) {
+ final ManagedList<Attribute> forRule = new ManagedList(accumulator.size());
+ forRule.addAll(accumulator);
+ ruleMap.put(ScriptTypeBeanParser.parseScriptType(ScriptedPredicate.class, child).getBeanDefinition(),
+ forRule);
}
child = ElementSupport.getNextSiblingElement(child);
}
builder.addPropertyValue("rules", ruleMap);
-
- if (element.hasAttributeNS(null, "attributeFilterRef")) {
- builder.addPropertyReference("attributeFilter",
- StringSupport.trimOrNull(element.getAttributeNS(null, "attributeFilterRef")));
- }
}
+// Checkstyle: CyclomaticComplexity ON
/** {@inheritDoc} */
@Override protected boolean shouldGenerateId() {
diff --git a/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/AbstractMetadataParserTest.java b/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/AbstractMetadataParserTest.java
index 5a76c34..0e5b094 100644
--- a/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/AbstractMetadataParserTest.java
+++ b/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/AbstractMetadataParserTest.java
@@ -44,6 +44,7 @@ import org.testng.annotations.BeforeSuite;
import net.shibboleth.ext.spring.config.DurationToLongConverter;
import net.shibboleth.ext.spring.config.StringToIPRangeConverter;
+import net.shibboleth.ext.spring.config.StringToResourceConverter;
import net.shibboleth.ext.spring.context.FilesystemGenericApplicationContext;
import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
import net.shibboleth.ext.spring.util.SpringSupport;
@@ -159,7 +160,10 @@ public class AbstractMetadataParserTest extends OpenSAMLInitBaseTestCase {
final ConversionServiceFactoryBean service = new ConversionServiceFactoryBean();
context.setDisplayName("ApplicationContext: " + contextName);
- service.setConverters(new HashSet<>(Arrays.asList(new DurationToLongConverter(), new StringToIPRangeConverter())));
+ service.setConverters(new HashSet<>(Arrays.asList(
+ new DurationToLongConverter(),
+ new StringToIPRangeConverter(),
+ new StringToResourceConverter())));
service.afterPropertiesSet();
context.getBeanFactory().setConversionService(service.getObject());
diff --git a/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/EntityAttributesFilterParserTest.java b/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/EntityAttributesFilterParserTest.java
index 3b9790c..8fd35d8 100644
--- a/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/EntityAttributesFilterParserTest.java
+++ b/idp-profile-spring/src/test/java/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/EntityAttributesFilterParserTest.java
@@ -38,9 +38,22 @@ public class EntityAttributesFilterParserTest extends AbstractMetadataParserTest
@Test
public void test() throws ResolverException, IOException {
+ doTest("filter/entityAttributes.xml", "filter/entityAttributesBeans.xml");
+ }
- final MetadataResolver resolver = getBean(MetadataResolver.class,
- "filter/entityAttributes.xml", "filter/entityAttributesBeans.xml");
+ @Test
+ public void testFilterScript() throws ResolverException, IOException {
+ doTest("filter/entityAttributesWithScript.xml");
+ }
+
+ @Test
+ public void testFilterScriptResource() throws ResolverException, IOException {
+ doTest("filter/entityAttributesWithScriptResource.xml");
+ }
+
+ private void doTest(final String... files) throws ResolverException, IOException {
+
+ final MetadataResolver resolver = getBean(MetadataResolver.class, files);
final EntityAttributesFilter filter = (EntityAttributesFilter) resolver.getMetadataFilter();
Assert.assertNotNull(filter);
@@ -73,5 +86,4 @@ public class EntityAttributesFilterParserTest extends AbstractMetadataParserTest
}
}
}
-
}
\ No newline at end of file
diff --git a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
index 3c2d282..fd30d2e 100644
--- a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
+++ b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
@@ -12,7 +12,8 @@
id="entityAttributes" xsi:type="metadata:InlineMetadataProvider">
- <metadata:MetadataFilter xsi:type="metadata:EntityAttributes" attributeFilterRef="predicate.AlwaysFalse">
+ <metadata:MetadataFilter xsi:type="metadata:EntityAttributes">
+ <metadata:AttributeFilterRef>predicate.AlwaysFalse</metadata:AttributeFilterRef>
<saml:Attribute Name="foo">
<saml:AttributeValue>fooValue</saml:AttributeValue>
</saml:Attribute>
diff --git a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesAttributeFilterScript.js b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesAttributeFilterScript.js
new file mode 100644
index 0000000..2372bb1
--- /dev/null
+++ b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesAttributeFilterScript.js
@@ -0,0 +1,2 @@
+
+!input.getName().equals("http://macedir.org/entity-category");
diff --git a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesConditionScript.js b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesConditionScript.js
new file mode 100644
index 0000000..9eefa45
--- /dev/null
+++ b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesConditionScript.js
@@ -0,0 +1,2 @@
+
+input.getEntityID().equals("https://sp.example.org/sp/shibboleth");
diff --git a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScript.xml
similarity index 87%
copy from idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
copy to idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScript.xml
index 3c2d282..b66fdc6 100644
--- a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
+++ b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScript.xml
@@ -12,14 +12,19 @@
id="entityAttributes" xsi:type="metadata:InlineMetadataProvider">
- <metadata:MetadataFilter xsi:type="metadata:EntityAttributes" attributeFilterRef="predicate.AlwaysFalse">
+ <metadata:MetadataFilter xsi:type="metadata:EntityAttributes">
+ <metadata:AttributeFilterScript>
+ <metadata:Script>!input.getName().equals("http://macedir.org/entity-category");</metadata:Script>
+ </metadata:AttributeFilterScript>
<saml:Attribute Name="foo">
<saml:AttributeValue>fooValue</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="bar">
<saml:AttributeValue>barValue</saml:AttributeValue>
</saml:Attribute>
- <metadata:Entity>https://sp.example.org/sp/shibboleth</metadata:Entity>
+ <metadata:ConditionScript language="javascript">
+ <metadata:Script>input.getEntityID().equals("https://sp.example.org/sp/shibboleth");</metadata:Script>
+ </metadata:ConditionScript>
</metadata:MetadataFilter>
<EntitiesDescriptor Name="ukgroup">
diff --git a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScriptResource.xml
similarity index 84%
copy from idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
copy to idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScriptResource.xml
index 3c2d282..989a445 100644
--- a/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributes.xml
+++ b/idp-profile-spring/src/test/resources/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesWithScriptResource.xml
@@ -12,14 +12,19 @@
id="entityAttributes" xsi:type="metadata:InlineMetadataProvider">
- <metadata:MetadataFilter xsi:type="metadata:EntityAttributes" attributeFilterRef="predicate.AlwaysFalse">
+ <metadata:MetadataFilter xsi:type="metadata:EntityAttributes">
+ <metadata:AttributeFilterScript>
+ <metadata:ScriptFile>classpath:/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesAttributeFilterScript.js</metadata:ScriptFile>
+ </metadata:AttributeFilterScript>
<saml:Attribute Name="foo">
<saml:AttributeValue>fooValue</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="bar">
<saml:AttributeValue>barValue</saml:AttributeValue>
</saml:Attribute>
- <metadata:Entity>https://sp.example.org/sp/shibboleth</metadata:Entity>
+ <metadata:ConditionScript language="javascript">
+ <metadata:ScriptFile>classpath:/net/shibboleth/idp/profile/spring/relyingparty/metadata/filter/entityAttributesConditionScript.js</metadata:ScriptFile>
+ </metadata:ConditionScript>
</metadata:MetadataFilter>
<EntitiesDescriptor Name="ukgroup">
diff --git a/idp-schema/src/main/resources/schema/shibboleth-metadata.xsd b/idp-schema/src/main/resources/schema/shibboleth-metadata.xsd
index 2c1e57d..7b274ae 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-metadata.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-metadata.xsd
@@ -1129,39 +1129,59 @@
</annotation>
<complexContent>
<extension base="shibmd:MetadataFilterType">
- <choice minOccurs="0" maxOccurs="unbounded">
- <element ref="saml:Attribute">
- <annotation>
- <documentation>
- An Attribute to add to an EntityAttributes extension.
- </documentation>
- </annotation>
- </element>
- <element name="Entity" type="string">
- <annotation>
- <documentation>
- An entityID to identify an EntityDescriptor to add all the preceding
- Attribute elements to.
- </documentation>
- </annotation>
- </element>
- <element name="ConditionRef" type="string">
- <annotation>
- <documentation>
- The ID of a Spring bean to inject as a condition Predicate to identify one
- or more EntityDescriptors to add all the preceding Attribute elements to.
- </documentation>
- </annotation>
- </element>
- </choice>
- <attribute name="attributeFilterRef" type="string">
- <annotation>
- <documentation>
- The ID of a Spring bean to inject as a condition Predicate to determine whether
- pre-existing EntityAttributes child Attributes should be retained.
- </documentation>
- </annotation>
- </attribute>
+ <sequence>
+ <choice minOccurs="0">
+ <element name="AttributeFilterRef" type="string">
+ <annotation>
+ <documentation>
+ The ID of a Spring bean to inject as a condition Predicate to determine whether
+ pre-existing EntityAttributes child Attributes should be retained.
+ </documentation>
+ </annotation>
+ </element>
+ <element name="AttributeFilterScript" type="shibmd:ScriptType" minOccurs="0">
+ <annotation>
+ <documentation>
+ A script implementing Predicate<Attribute> to determine whether
+ pre-existing EntityAttributes child Attributes should be retained.
+ </documentation>
+ </annotation>
+ </element>
+ </choice>
+ <choice minOccurs="0" maxOccurs="unbounded">
+ <element ref="saml:Attribute">
+ <annotation>
+ <documentation>
+ An Attribute to add to an EntityAttributes extension.
+ </documentation>
+ </annotation>
+ </element>
+ <element name="Entity" type="string">
+ <annotation>
+ <documentation>
+ An entityID to identify an EntityDescriptor to add all the preceding
+ Attribute elements to.
+ </documentation>
+ </annotation>
+ </element>
+ <element name="ConditionRef" type="string">
+ <annotation>
+ <documentation>
+ The ID of a Spring bean to inject as a condition Predicate to identify one
+ or more EntityDescriptors to add all the preceding Attribute elements to.
+ </documentation>
+ </annotation>
+ </element>
+ <element name="ConditionScript" type="shibmd:ScriptType">
+ <annotation>
+ <documentation>
+ A script implementing Predicate<EntityDescriptor> to identify one
+ or more EntityDescriptors to add all the preceding Attribute elements to.
+ </documentation>
+ </annotation>
+ </element>
+ </choice>
+ </sequence>
</extension>
</complexContent>
</complexType>
@@ -1338,4 +1358,42 @@
</complexType>
<complexType name="MetadataNodeProcessorType" abstract="true"/>
+
+ <complexType name="ScriptType">
+ <annotation>
+ <documentation>
+ A type for elements that allow for scripts to be declared inline or via a resource.
+ </documentation>
+ </annotation>
+ <choice>
+ <element name="Script" type="string">
+ <annotation>
+ <documentation>The script to evaluate to construct the attribute.</documentation>
+ </annotation>
+ </element>
+ <element name="ScriptFile" type="string">
+ <annotation>
+ <documentation>
+ Path of a local resource containing the script to evaluate to construct the attribute.
+ </documentation>
+ </annotation>
+ </element>
+ </choice>
+ <attribute name="language" type="string">
+ <annotation>
+ <documentation>
+ The JSR-233 name for the scripting language that will be used.
+ By default "javascript" is assumed.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="customObjectRef" type="string">
+ <annotation>
+ <documentation>
+ The name of a bean defined somewhere else which will be injected into the script as an
+ object called "custom". If not supplied, nothing is injected.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
</schema>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list