[java-identity-provider] branch master updated: Extend attribute mapping and mapped predicate to EntitiesDescriptors.
Scott Cantor
cantor.2 at osu.edu
Mon May 20 19:07:35 EDT 2019
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=4211594238859df0173eedf1c70c599d4627e0b5
The following commit(s) were added to refs/heads/master by this push:
new 4211594 Extend attribute mapping and mapped predicate to EntitiesDescriptors.
4211594 is described below
commit 4211594238859df0173eedf1c70c599d4627e0b5
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon May 20 19:07:29 2019 -0400
Extend attribute mapping and mapped predicate to EntitiesDescriptors.
---
.../logic/MappedEntityAttributesPredicate.java | 73 +++++++++++++++-------
.../impl/AttributeMappingNodeProcessor.java | 24 ++++---
.../impl/EntityAttributesPredicateTest.java | 34 ++++++++++
.../impl/metadata/attribute-mapping-metadata.xml | 13 ++--
.../shibboleth/idp/saml/impl/metadata/rules/rs.txt | 3 -
5 files changed, 109 insertions(+), 38 deletions(-)
diff --git a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/logic/MappedEntityAttributesPredicate.java b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/logic/MappedEntityAttributesPredicate.java
index f091832..0882daf 100644
--- a/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/logic/MappedEntityAttributesPredicate.java
+++ b/idp-saml-api/src/main/java/net/shibboleth/idp/saml/profile/logic/MappedEntityAttributesPredicate.java
@@ -17,6 +17,7 @@
package net.shibboleth.idp.saml.profile.logic;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
@@ -24,7 +25,9 @@ import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.opensaml.core.xml.XMLObject;
import org.opensaml.saml.common.profile.logic.EntityAttributesPredicate;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -68,7 +71,7 @@ public class MappedEntityAttributesPredicate extends EntityAttributesPredicate {
super(candidates);
Constraint.isTrue(Iterables.all(candidates, c -> c.getNameFormat() == null),
- "Use of nameFormat property is impermissible for MappedEntityAttributesPredicate");
+ "Use of nameFormat property is impermissible with MappedEntityAttributesPredicate");
}
/**
@@ -83,7 +86,7 @@ public class MappedEntityAttributesPredicate extends EntityAttributesPredicate {
super(candidates, trim);
Constraint.isTrue(Iterables.all(candidates, c -> c.getNameFormat() == null),
- "Use of nameFormat property is impermissible for MappedEntityAttributesPredicate");
+ "Use of nameFormat property is impermissible with MappedEntityAttributesPredicate");
}
/**
@@ -100,7 +103,7 @@ public class MappedEntityAttributesPredicate extends EntityAttributesPredicate {
super(candidates, trim, all);
Constraint.isTrue(Iterables.all(candidates, c -> c.getNameFormat() == null),
- "Use of nameFormat property is impermissible for MappedEntityAttributesPredicate");
+ "Use of nameFormat property is impermissible with MappedEntityAttributesPredicate");
}
/**
@@ -119,38 +122,64 @@ public class MappedEntityAttributesPredicate extends EntityAttributesPredicate {
@Override
public boolean test(@Nullable final EntityDescriptor input) {
- if (input == null) {
- return false;
+ if (input == null || getCandidates().isEmpty()) {
+ return true;
}
+
+ final Collection<Candidate> candidates = new ArrayList<>(getCandidates());
+ if (doTest(input, input.getEntityID(), candidates)) {
+
+ // At least one match. Check if sufficient.
+ if (!getMatchAll() || candidates.isEmpty()) {
+ return true;
+ }
+ }
+
+ XMLObject parent = input.getParent();
+ while (parent instanceof EntitiesDescriptor) {
+ if (doTest(parent, ((EntitiesDescriptor) parent).getName(), candidates)) {
+
+ // At least one match. Check if sufficient.
+ if (!getMatchAll() || candidates.isEmpty()) {
+ return true;
+ }
+ }
+ parent = parent.getParent();
+ }
+
+ return false;
+ }
+
+ /**
+ * Evaluate the input object's attached object metadata against the supplied candidates.
+ *
+ * <p>Any candidates that match will be removed from the input collection.</p>
+ *
+ * @param input input object
+ * @param name label for logging
+ * @param candidates candidates to check
+ *
+ * @return true iff the attached object metadata matched at least one input candidate
+ */
+ private boolean doTest(@Nullable final XMLObject input, @Nullable final String name,
+ @Nonnull @NonnullElements final Collection<Candidate> candidates) {
final List<AttributesMapContainer> containerList =
input.getObjectMetadata().get(AttributesMapContainer.class);
if (null == containerList || containerList.isEmpty() || containerList.get(0).get() == null ||
containerList.get(0).get().isEmpty()) {
- log.trace("No mapped Entity Attributes for {}", input.getEntityID());
+ log.trace("No mapped Entity Attributes for {}", name);
return false;
}
final Multimap<String,? extends IdPAttribute> entityAttributes = containerList.get(0).get();
log.trace("Checking for match against {} Entity Attributes for {}", entityAttributes.size(),
- input.getEntityID());
-
- // If we find a matching tag, we win. Each tag is treated in OR fashion.
- final EntityAttributesMatcher matcher = new EntityAttributesMatcher(entityAttributes);
+ name);
- // Then we determine whether the overall set of tag containers is AND or OR.
- if (getMatchAll()) {
- if (Iterables.all(getCandidates(), matcher::test)) {
- return true;
- }
- } else {
- if (Iterables.tryFind(getCandidates(), matcher::test).isPresent()) {
- return true;
- }
- }
-
- return false;
+ // Remove each candidate that matches. Tag values are OR'd for matching purposes.
+ // Return true iff at least one candidate matches.
+ return candidates.removeIf(new EntityAttributesMatcher(entityAttributes));
}
/**
diff --git a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
index 14e8581..d949eeb 100644
--- a/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
+++ b/idp-saml-impl/src/main/java/net/shibboleth/idp/saml/metadata/impl/AttributeMappingNodeProcessor.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import net.shibboleth.idp.attribute.AttributeDecodingException;
@@ -50,6 +51,7 @@ import org.opensaml.saml.metadata.resolver.filter.FilterException;
import org.opensaml.saml.metadata.resolver.filter.MetadataNodeProcessor;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.metadata.AttributeConsumingService;
+import org.opensaml.saml.saml2.metadata.EntitiesDescriptor;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.opensaml.saml.saml2.metadata.Extensions;
import org.opensaml.saml.saml2.metadata.RequestedAttribute;
@@ -109,7 +111,12 @@ public class AttributeMappingNodeProcessor implements MetadataNodeProcessor {
if (component == null) {
log.error("Attribute transcoding service unavailable");
} else {
- handleEntityDescriptor(component.getComponent(), (EntityDescriptor) metadataNode);
+ handleEntityAttributes(component.getComponent(), ((EntityDescriptor) metadataNode).getExtensions());
+ XMLObject parent = metadataNode.getParent();
+ while (parent instanceof EntitiesDescriptor) {
+ handleEntityAttributes(component.getComponent(), ((EntitiesDescriptor) parent).getExtensions());
+ parent = parent.getParent();
+ }
}
}
} finally {
@@ -148,15 +155,14 @@ public class AttributeMappingNodeProcessor implements MetadataNodeProcessor {
}
/**
- * Look inside the {@link EntityDescriptor} for entities Attributes and map them.
+ * Look inside the {@link Extensions} for {@link EntityAttributes) and map them.
*
* @param registry the registry service
- * @param entity the entity
+ * @param extensions the extensions block
*/
-//CheckStyle: CyclomaticComplexity|ReturnCount OFF
- private void handleEntityDescriptor(@Nonnull final AttributeTranscoderRegistry registry,
- @Nonnull final EntityDescriptor entity) {
- final Extensions extensions = entity.getExtensions();
+//CheckStyle: CyclomaticComplexity OFF
+ private void handleEntityAttributes(@Nonnull final AttributeTranscoderRegistry registry,
+ @Nullable final Extensions extensions) {
if (null == extensions) {
return;
}
@@ -195,10 +201,10 @@ public class AttributeMappingNodeProcessor implements MetadataNodeProcessor {
}
if (!results.isEmpty()) {
- entity.getObjectMetadata().put(new AttributesMapContainer<>(results));
+ extensions.getParent().getObjectMetadata().put(new AttributesMapContainer<>(results));
}
}
- //CheckStyle: CyclomaticComplexity|ReturnCount ON
+ //CheckStyle: CyclomaticComplexity ON
/**
* Access the registry of transcoding rules to decode the input object.
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/EntityAttributesPredicateTest.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/EntityAttributesPredicateTest.java
index 090d43b..24f9b65 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/EntityAttributesPredicateTest.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/metadata/impl/EntityAttributesPredicateTest.java
@@ -58,6 +58,8 @@ public class EntityAttributesPredicateTest extends XMLObjectBaseTestCase {
private String barEntityID = "http://bar.example.org/shibboleth";
+ private String bazEntityID = "http://baz.example.org/shibboleth";
+
private GenericApplicationContext pendingTeardownContext = null;
private MetadataResolver resolver = null;
@@ -129,9 +131,25 @@ public class EntityAttributesPredicateTest extends XMLObjectBaseTestCase {
final EntityAttributesPredicate predicate = new EntityAttributesPredicate(Collections.singletonList(tag));
Assert.assertFalse(predicate.test(getEntity(fooEntityID)));
Assert.assertTrue(predicate.test(getEntity(barEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(bazEntityID)));
}
@Test
+ public void testMultiLevelMatch() throws ResolverException {
+ final Candidate tag1 = new Candidate("http://macedir.org/entity-category", Attribute.URI_REFERENCE);
+ tag1.setValues(Collections.singletonList("http://refeds.org/category/research-and-scholarship"));
+
+ final Candidate tag2 = new Candidate("urn:oasis:names:tc:SAML:profiles:subject-id:req", Attribute.URI_REFERENCE);
+ tag2.setValues(Collections.singletonList("none"));
+
+ final EntityAttributesPredicate predicate =
+ new EntityAttributesPredicate(Arrays.asList(tag1, tag2), false, true);
+ Assert.assertTrue(predicate.test(getEntity(fooEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(barEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(bazEntityID)));
+ }
+
+ @Test
public void testSimpleMatchMapped() throws ResolverException {
final Candidate tag = new Candidate("zorkmids");
@@ -140,6 +158,22 @@ public class EntityAttributesPredicateTest extends XMLObjectBaseTestCase {
final MappedEntityAttributesPredicate predicate = new MappedEntityAttributesPredicate(Collections.singletonList(tag));
Assert.assertFalse(predicate.test(getEntity(fooEntityID)));
Assert.assertTrue(predicate.test(getEntity(barEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(bazEntityID)));
+ }
+
+ @Test
+ public void testMultiLevelMappedMatch() throws ResolverException {
+ final Candidate tag1 = new Candidate("http://macedir.org/entity-category");
+ tag1.setValues(Collections.singletonList("http://refeds.org/category/research-and-scholarship"));
+
+ final Candidate tag2 = new Candidate("subject-id-req");
+ tag2.setValues(Collections.singletonList("none"));
+
+ final MappedEntityAttributesPredicate predicate =
+ new MappedEntityAttributesPredicate(Arrays.asList(tag1, tag2), false, true);
+ Assert.assertTrue(predicate.test(getEntity(fooEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(barEntityID)));
+ Assert.assertFalse(predicate.test(getEntity(bazEntityID)));
}
}
\ No newline at end of file
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/attribute-mapping-metadata.xml b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/attribute-mapping-metadata.xml
index 6a5077a..a9850f5 100644
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/attribute-mapping-metadata.xml
+++ b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/attribute-mapping-metadata.xml
@@ -3,15 +3,20 @@
xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
-
- <EntityDescriptor entityID="http://foo.example.org/shibboleth">
-
- <Extensions>
+
+ <Extensions>
<mdattr:EntityAttributes>
<saml:Attribute Name="http://macedir.org/entity-category"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>http://refeds.org/category/research-and-scholarship</saml:AttributeValue>
</saml:Attribute>
+ </mdattr:EntityAttributes>
+ </Extensions>
+
+ <EntityDescriptor entityID="http://foo.example.org/shibboleth">
+
+ <Extensions>
+ <mdattr:EntityAttributes>
<saml:Attribute Name="urn:oasis:names:tc:SAML:profiles:subject-id:req"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>none</saml:AttributeValue>
diff --git a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/rules/rs.txt b/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/rules/rs.txt
deleted file mode 100644
index 12d0bc8..0000000
--- a/idp-saml-impl/src/test/resources/net/shibboleth/idp/saml/impl/metadata/rules/rs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-id = rands
-transcoderBean = SAML2StringTranscoder
-name = http://macedir.org/entity-category
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list