[java-metadata-aggregator] 01/03: MDA-55 add ability to filter entity attribute values
Ian Young
ian at iay.org.uk
Fri Dec 4 10:52:31 EST 2015
This is an automated email from the git hooks/post-receive script.
iay pushed a commit to branch master
in repository java-metadata-aggregator.
commit 8bf78d68d7c51f1286e8310cd7d6b04364a3115f
Author: Ian Young <ian at iay.org.uk>
AuthorDate: Fri Dec 4 08:55:31 2015 +0000
MDA-55 add ability to filter entity attribute values
Initial import from ukf-mda project, tidied up a little.
---
.../shibboleth/metadata/dom/saml/SAMLSupport.java | 67 ++++++
.../mdattr/AbstractEntityAttributeMatcher.java | 79 +++++++
.../dom/saml/mdattr/AbstractExactValueMatcher.java | 90 ++++++++
.../dom/saml/mdattr/EntityAttributeContext.java | 64 ++++++
.../saml/mdattr/EntityAttributeFilteringStage.java | 238 +++++++++++++++++++++
.../dom/saml/mdattr/EntityCategoryMatcher.java | 50 +++++
.../dom/saml/mdattr/EntityCategorySupport.java | 44 ++++
.../saml/mdattr/EntityCategorySupportMatcher.java | 50 +++++
.../metadata/dom/saml/mdattr/MDAttrSupport.java | 40 ++++
.../dom/saml/mdattr/MultiPredicateMatcher.java | 155 ++++++++++++++
.../saml/mdattr/RegistrationAuthorityMatcher.java | 58 +++++
.../saml/mdattr/SimpleEntityAttributeContext.java | 112 ++++++++++
.../metadata/dom/saml/mdattr/package-info.java | 21 ++
.../mdattr/EntityAttributeFilteringStageTest.java | 175 +++++++++++++++
.../mdattr/EntityCategoryMatcherSpringTest.java | 71 ++++++
.../dom/saml/mdattr/EntityCategoryMatcherTest.java | 60 ++++++
.../mdattr/EntityCategorySupportMatcherTest.java | 60 ++++++
.../dom/saml/mdattr/MultiPredicateMatcherTest.java | 57 +++++
.../mdattr/RegistrationAuthorityMatcherTest.java | 34 +++
.../mdattr/SimpleEntityAttributeContextTest.java | 40 ++++
.../EntityAttributeFilteringStage-blacklist.xml | 65 ++++++
.../mdattr/EntityAttributeFilteringStage-input.xml | 65 ++++++
.../EntityAttributeFilteringStage-keepcoc.xml | 60 ++++++
.../EntityAttributeFilteringStage-keepcoc2.xml | 63 ++++++
.../EntityAttributeFilteringStage-keepnone.xml | 53 +++++
.../EntityCategoryMatcherSpringTest-config.xml | 20 ++
26 files changed, 1891 insertions(+)
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/SAMLSupport.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/SAMLSupport.java
new file mode 100644
index 0000000..609e2b4
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/SAMLSupport.java
@@ -0,0 +1,67 @@
+/*
+ * 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.metadata.dom.saml;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import javax.xml.namespace.QName;
+
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+/** Helper class for dealing with SAML documents. */
+ at ThreadSafe
+public final class SAMLSupport {
+
+ /** Namespace URI for SAML elements. */
+ public static final String SAML_NS = "urn:oasis:names:tc:SAML:2.0:assertion";
+
+ /** Conventional prefix for SAML elements. */
+ public static final String SAML_PREFIX = "saml";
+
+ /** saml:Attribute element. */
+ public static final QName ATTRIBUTE_NAME = new QName(SAML_NS, "Attribute", SAML_PREFIX);
+
+ /** Unspecified default <code>NameFormat</code> value for <code>Attribute</code> elements. */
+ public static final String ATTRNAME_FORMAT_UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
+
+ /** saml:AttributeValue element. */
+ public static final QName ATTRIBUTE_VALUE_NAME = new QName(SAML_NS, "AttributeValue", SAML_PREFIX);
+
+ /** Constructor. */
+ private SAMLSupport() {
+ }
+
+ /**
+ * Extract an <code>Attribute</code> element's <code>NameFormat</code>, applying the
+ * SAML standard's specified default if the XML attribute is not present.
+ *
+ * @param attribute <code>Attribute</code> {@link Element}
+ * @return <code>NameFormat</code> value, or the "unspecified" default
+ */
+ @Nonnull
+ public static String extractAttributeNameFormat(@Nonnull final Element attribute) {
+ final Attr attr = attribute.getAttributeNode("NameFormat");
+ if (attr == null) {
+ return ATTRNAME_FORMAT_UNSPECIFIED;
+ } else {
+ return attr.getValue();
+ }
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractEntityAttributeMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractEntityAttributeMatcher.java
new file mode 100644
index 0000000..9ae9601
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractEntityAttributeMatcher.java
@@ -0,0 +1,79 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import com.google.common.base.Predicate;
+
+/**
+ * Abstract implementation of {@link Predicate} over {@link EntityAttributeContext} using
+ * the template method pattern. The {@link #apply} method is broken down into matches
+ * against the four components of the {@link EntityAttributeContext}. All four sub-matches
+ * must succeed for the {@link Predicate} to be <code>true</code>
+ *
+ * Where an implementation wishes to ignore a component (most commonly,
+ * {@link EntityAttributeContext#getRegistrationAuthority}) it can simply return <code>true</code>
+ * in that template method.
+ */
+ at ThreadSafe
+public abstract class AbstractEntityAttributeMatcher implements Predicate<EntityAttributeContext> {
+
+ /**
+ * Match the attribute value component of the {@link EntityAttributeContext}.
+ *
+ * @param inputValue value component of the input context
+ * @return <code>true</code> if and only if the value component matches
+ */
+ protected abstract boolean matchAttributeValue(@Nonnull final String inputValue);
+
+ /**
+ * Match the name component of the {@link EntityAttributeContext}.
+ *
+ * @param inputName name component of the input context
+ * @return <code>true</code> if and only if the name component matches
+ */
+ protected abstract boolean matchAttributeName(@Nonnull final String inputName);
+
+ /**
+ * Match the name format component of the {@link EntityAttributeContext}.
+ *
+ * @param inputNameFormat name format component of the input context
+ * @return <code>true</code> if and only if the name format component matches
+ */
+ protected abstract boolean matchAttributeNameFormat(@Nonnull final String inputNameFormat);
+
+ /**
+ * Match the registration authority component of the {@link EntityAttributeContext}.
+ *
+ * @param inputRegistrationAuthority registration authority component of the input context
+ * @return <code>true</code> if and only if the registration authority component matches
+ */
+ protected abstract boolean matchRegistrationAuthority(@Nullable final String inputRegistrationAuthority);
+
+ @Override
+ public boolean apply(@Nonnull final EntityAttributeContext input) {
+ return matchRegistrationAuthority(input.getRegistrationAuthority()) &&
+ matchAttributeNameFormat(input.getNameFormat()) &&
+ matchAttributeName(input.getName()) &&
+ matchAttributeValue(input.getValue());
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractExactValueMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractExactValueMatcher.java
new file mode 100644
index 0000000..a5c5f61
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/AbstractExactValueMatcher.java
@@ -0,0 +1,90 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * An abstract entity attribute matcher implementation that matches an exact
+ * combination of value, name and name format. Optionally, a registration
+ * authority value may also be matched against.
+ */
+ at ThreadSafe
+public abstract class AbstractExactValueMatcher extends AbstractEntityAttributeMatcher {
+
+ /** The attribute value to match. */
+ private final String value;
+
+ /** The attribute <code>Name</code> to match. */
+ private final String name;
+
+ /** The attribute <code>NameFormat</code> to match. */
+ private final String nameFormat;
+
+ /** Registration authority to match against, or <code>null</code>. */
+ @Nullable
+ private final String registrationAuthority;
+
+ /**
+ * Constructor.
+ *
+ * @param matchValue attribute value to match
+ * @param matchName attribute name to match
+ * @param matchNameFormat attribute name format to match
+ * @param matchRegAuth entity registration authority to match, or <code>null</code>
+ */
+ public AbstractExactValueMatcher(@Nonnull final String matchValue,
+ @Nonnull final String matchName, @Nonnull final String matchNameFormat,
+ @Nullable final String matchRegAuth) {
+ super();
+ value = Constraint.isNotNull(matchValue, "value may not be null");
+ name = Constraint.isNotNull(matchName, "name may not be null");
+ nameFormat = Constraint.isNotNull(matchNameFormat, "name format may not be null");
+ registrationAuthority = matchRegAuth;
+ }
+
+ @Override
+ protected boolean matchAttributeValue(@Nonnull final String inputValue) {
+ return value.equals(inputValue);
+ }
+
+ @Override
+ protected boolean matchAttributeName(@Nonnull final String inputName) {
+ return name.equals(inputName);
+ }
+
+ @Override
+ protected boolean matchAttributeNameFormat(@Nonnull final String inputNameFormat) {
+ return nameFormat.equals(inputNameFormat);
+ }
+
+ @Override
+ protected boolean matchRegistrationAuthority(@Nullable final String inputRegistrationAuthority) {
+ if (registrationAuthority == null) {
+ // ignore the context's registration authority value
+ return true;
+ } else {
+ return registrationAuthority.equals(inputRegistrationAuthority);
+ }
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeContext.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeContext.java
new file mode 100644
index 0000000..1ff96e7
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeContext.java
@@ -0,0 +1,64 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * An entity attribute context against which matches can take place. It consists
+ * of the attribute's value, <code>Name</code> and <code>NameFormat</code> attributes,
+ * and the entity's <code>registrationAuthority</code>, if any.
+ *
+ * A matcher is a {@link com.google.common.base.Predicate} over such a context.
+ */
+public interface EntityAttributeContext {
+
+ /**
+ * Returns the registration authority component, or <code>null</code>.
+ *
+ * @return the registration authority, or <code>null</code>
+ */
+ @Nullable
+ String getRegistrationAuthority();
+
+ /**
+ * Returns the attribute's <code>NameFormat</code>.
+ *
+ * @return the attribute's <code>NameFormat</code>.
+ */
+ @Nonnull
+ String getNameFormat();
+
+ /**
+ * Returns the attribute's <code>Name</code>.
+ *
+ * @return the attribute's <code>Name</code>
+ */
+ @Nonnull
+ String getName();
+
+ /**
+ * Returns the attribute's value.
+ *
+ * @return the attribute's value
+ */
+ @Nonnull
+ String getValue();
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage.java
new file mode 100644
index 0000000..978a2b2
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage.java
@@ -0,0 +1,238 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.metadata.Item;
+import net.shibboleth.metadata.dom.saml.SAMLMetadataSupport;
+import net.shibboleth.metadata.dom.saml.SAMLSupport;
+import net.shibboleth.metadata.dom.saml.mdrpi.RegistrationAuthority;
+import net.shibboleth.metadata.pipeline.BaseStage;
+import net.shibboleth.metadata.pipeline.StageProcessingException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.xml.ElementSupport;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import com.google.common.base.Predicate;
+
+/**
+ * A stage which filters entity attributes from entity definitions according to a supplied
+ * set of rules.
+ *
+ * For each attribute value under consideration, a {@link EntityAttributeContext} is built
+ * from the components of the attribute and the entity's <code>registrationAuthority</code>,
+ * if any.
+ *
+ * Note that the <code>registrationAuthority</code> to be used is assumed to have been
+ * extracted out into a {@link RegistrationAuthority} object in the entity's item metadata.
+ *
+ * The stage can be operated in a whitelisting mode (the default) or in a blacklisting mode
+ * by setting the <code>whitelisting</code> property to <code>false</code>.
+ */
+public class EntityAttributeFilteringStage extends BaseStage<Element> {
+
+ /** Class logger. */
+ private final Logger log = LoggerFactory.getLogger(EntityAttributeFilteringStage.class);
+
+ /**
+ * List of matching rules to apply to each attribute value. The list is applied in
+ * order, with the first rule returning <code>true</code> terminating the evaluation.
+ * This amounts to an implicit ORing of the individual rules, with early
+ * termination.
+ */
+ private List<Predicate<EntityAttributeContext>> rules = Collections.emptyList();
+
+ /** Mode of operation: whitelisting or blacklisting. Default: whitelisting. */
+ private boolean whitelisting = true;
+
+ /**
+ * Sets the {@link List} of rules to be used to match attribute values.
+ *
+ * @param newRules new {@link List} of rules
+ */
+ public void setRules(@Nonnull final List<Predicate<EntityAttributeContext>> newRules) {
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ rules = Constraint.isNotNull(newRules, "rules property may not be null");
+ }
+
+ /**
+ * Returns the {@link List} of rules being used to match entity attributes.
+ *
+ * @return the {@link List} of rules
+ */
+ @Nonnull
+ public List<Predicate<EntityAttributeContext>> getRules() {
+ return Collections.unmodifiableList(rules);
+ }
+
+ /**
+ * Sets the mode of operation.
+ *
+ * @param newValue <code>true</code> to whitelist (default),
+ * <code>false</code> to blacklist
+ */
+ public void setWhitelisting(final boolean newValue) {
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ whitelisting = newValue;
+ }
+
+ /**
+ * Indicates whether the stage is set to whitelisting or blacklisting mode.
+ *
+ * @return <code>true</code> if whitelisting (default),
+ * <code>false</code> if blacklisting
+ */
+ public boolean isWhitelisting() {
+ return whitelisting;
+ }
+
+ /**
+ * Apply the rules to a context.
+ *
+ * @param ctx the context to apply the rules to
+ * @return <code>true</code> if one of the rules returns <code>true</code>;
+ * otherwise <code>false</code>
+ */
+ private boolean applyRules(final EntityAttributeContext ctx) {
+ for (final Predicate<EntityAttributeContext> rule : rules) {
+ if (rule.apply(ctx)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Extract the registration authority for an entity from its entity metadata.
+ *
+ * @param item the {@link Item} representing the entity
+ * @return the registration authority URI, or <code>null</code> if not present
+ */
+ private String extractRegistrationAuthority(@Nonnull final Item<Element> item) {
+ final List<RegistrationAuthority> regAuthList = item.getItemMetadata().get(RegistrationAuthority.class);
+ if (regAuthList.isEmpty()) {
+ return null;
+ } else {
+ return regAuthList.get(0).getRegistrationAuthority();
+ }
+ }
+
+ /**
+ * Filter an <code>Attribute</code> element.
+ *
+ * @param attribute an <code>Attribute</code> element to filter
+ * @param registrationAuthority the registration authority associated with the entity
+ */
+ private void filterAttribute(@Nonnull final Element attribute, @Nullable final String registrationAuthority) {
+ // Determine the attribute's name; this will default to the empty string if not present
+ final String attributeName = attribute.getAttribute("Name");
+
+ // Determine the attribute's NameFormat
+ final String attributeNameFormat = SAMLSupport.extractAttributeNameFormat(attribute);
+
+ // Locate the AttributeValue elements to filter
+ final List<Element> attributeValues =
+ ElementSupport.getChildElements(attribute, SAMLSupport.ATTRIBUTE_VALUE_NAME);
+
+ // Filter each AttributeValue in turn
+ for (final Element value : attributeValues) {
+ final String attributeValue = value.getTextContent();
+
+ // Construct an entity attribute context to be matched against
+ final EntityAttributeContext ctx =
+ new SimpleEntityAttributeContext(attributeValue, attributeName,
+ attributeNameFormat, registrationAuthority);
+ final boolean matched = applyRules(ctx);
+ if (matched ^ whitelisting) {
+ log.debug("removing {}", ctx);
+ attribute.removeChild(value);
+ }
+ }
+ }
+
+ /**
+ * Filter an <code>EntityAttributes</code> extension element.
+ *
+ * @param entityAttributes the <code>EntityAttributes</code> extension element
+ * @param registrationAuthority the registration authority associated with the entity
+ */
+ private void filterEntityAttributes(@Nonnull final Element entityAttributes,
+ @Nullable final String registrationAuthority) {
+ // Locate the Attribute elements to filter
+ final List<Element> attributes =
+ ElementSupport.getChildElements(entityAttributes, SAMLSupport.ATTRIBUTE_NAME);
+
+ // Filter each Attribute in turn
+ for (final Element attribute : attributes) {
+ filterAttribute(attribute, registrationAuthority);
+
+ // remove the Attribute container if it is now empty
+ if (ElementSupport.getFirstChildElement(attribute) == null) {
+ log.debug("removing empty Attribute");
+ entityAttributes.removeChild(attribute);
+ }
+ }
+ }
+
+ @Override
+ protected void doExecute(final Collection<Item<Element>> itemCollection) throws StageProcessingException {
+ for (final Item<Element> item : itemCollection) {
+ final Element entity = item.unwrap();
+
+ // Establish the item's registrationAuthority, if any
+ final String registrationAuthority = extractRegistrationAuthority(item);
+
+ // Locate mdattr:EntityAttributes element
+ final Element entityAttributes = SAMLMetadataSupport.getDescriptorExtensions(entity,
+ MDAttrSupport.ENTITY_ATTRIBUTES_NAME);
+ if (entityAttributes != null) {
+ filterEntityAttributes(entityAttributes, registrationAuthority);
+
+ // remove the EntityAttributes container if it is now empty
+ if (ElementSupport.getFirstChildElement(entityAttributes) == null) {
+ log.debug("removing empty EntityAttributes");
+ final Node extensions = entityAttributes.getParentNode();
+ extensions.removeChild(entityAttributes);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void doDestroy() {
+ rules = null;
+
+ super.doDestroy();
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcher.java
new file mode 100644
index 0000000..a5d13c6
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcher.java
@@ -0,0 +1,50 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * An entity attribute matcher which matches a given entity category.
+ */
+ at ThreadSafe
+public class EntityCategoryMatcher extends AbstractExactValueMatcher {
+
+ /**
+ * Constructor.
+ *
+ * @param category entity category to match
+ * @param regAuth registration authority to match, or <code>null</code>
+ */
+ public EntityCategoryMatcher(@Nonnull final String category, @Nullable final String regAuth) {
+ super(category, EntityCategorySupport.EC_CATEGORY_ATTR_NAME,
+ EntityCategorySupport.EC_ATTR_NAME_FORMAT, regAuth);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param category entity category to match
+ */
+ public EntityCategoryMatcher(@Nonnull final String category) {
+ this(category, null);
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupport.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupport.java
new file mode 100644
index 0000000..886d607
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupport.java
@@ -0,0 +1,44 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * Helper class for dealing with entity categories.
+ *
+ * @see <a href="https://datatracker.ietf.org/doc/draft-young-entity-category/">
+ * The Entity Category SAML Attribute Types</a>
+ */
+ at ThreadSafe
+public final class EntityCategorySupport {
+
+ /** The attribute <code>NameFormat</code> for all entity category attributes. */
+ public static final String EC_ATTR_NAME_FORMAT = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri";
+
+ /** The attribute <code>Name</code> for the Entity Category Attribute. */
+ public static final String EC_CATEGORY_ATTR_NAME = "http://macedir.org/entity-category";
+
+ /** The attribute <code>Name</code> for the Entity Category Support Attribute. */
+ public static final String EC_SUPPORT_ATTR_NAME = "http://macedir.org/entity-category-support";
+
+ /** Constructor. */
+ private EntityCategorySupport() {
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcher.java
new file mode 100644
index 0000000..7be1ada
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcher.java
@@ -0,0 +1,50 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * An entity attribute matcher which matches a given entity support category.
+ */
+ at ThreadSafe
+public class EntityCategorySupportMatcher extends AbstractExactValueMatcher {
+
+ /**
+ * Constructor.
+ *
+ * @param category entity category to match
+ * @param regAuth registration authority to match, or <code>null</code>
+ */
+ public EntityCategorySupportMatcher(@Nonnull final String category, @Nullable final String regAuth) {
+ super(category, EntityCategorySupport.EC_SUPPORT_ATTR_NAME,
+ EntityCategorySupport.EC_ATTR_NAME_FORMAT, regAuth);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param category entity category to match
+ */
+ public EntityCategorySupportMatcher(@Nonnull final String category) {
+ this(category, null);
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MDAttrSupport.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MDAttrSupport.java
new file mode 100644
index 0000000..1f456cf
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MDAttrSupport.java
@@ -0,0 +1,40 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.concurrent.ThreadSafe;
+import javax.xml.namespace.QName;
+
+/** Helper class for dealing with MDAttr metadata. */
+ at ThreadSafe
+public final class MDAttrSupport {
+
+ /** MDAttr namespace. */
+ public static final String MDATTR_NS = "urn:oasis:names:tc:SAML:metadata:attribute";
+
+ /** MDAttr conventional prefix. */
+ public static final String MDATTR_PREFIX = "mdattr";
+
+ /** mdattr:EntityAttributes element. */
+ public static final QName ENTITY_ATTRIBUTES_NAME = new QName(MDATTR_NS, "EntityAttributes", MDATTR_PREFIX);
+
+ /** Constructor. */
+ private MDAttrSupport() {
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcher.java
new file mode 100644
index 0000000..42e0073
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcher.java
@@ -0,0 +1,155 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+/**
+ * An entity attribute matcher implementation that delegates each
+ * component match to a different @{link Predicate}. Each such
+ * {@link Predicate} defaults to {@link Predicates#alwaysTrue} so that
+ * in most cases a minimum number of properties need to be set.
+ *
+ * The individual {@link Predicate}s operate over {@link CharSequence}
+ * rather than {@link String} both for generality and to allow the use
+ * of instances produced by {@link Predicates#containsPattern}.
+ */
+ at ThreadSafe
+public class MultiPredicateMatcher extends AbstractEntityAttributeMatcher {
+
+ /** {@link Predicate} to use to match the context's attribute value. */
+ @Nonnull
+ private Predicate<CharSequence> valuePredicate = Predicates.alwaysTrue();
+
+ /** {@link Predicate} to use to match the context's attribute name. */
+ @Nonnull
+ private Predicate<CharSequence> namePredicate = Predicates.alwaysTrue();
+
+ /** {@link Predicate} to use to match the context's attribute name format. */
+ @Nonnull
+ private Predicate<CharSequence> nameFormatPredicate = Predicates.alwaysTrue();
+
+ /** {@link Predicate} to use to match the context's registration authority. */
+ @Nonnull
+ private Predicate<CharSequence> registrationAuthorityPredicate = Predicates.alwaysTrue();
+
+ /**
+ * Gets the {@link Predicate} being used to match the context's attribute value.
+ *
+ * @return the {@link Predicate} being used to match the context's attribute value
+ */
+ @Nonnull
+ public Predicate<CharSequence> getValuePredicate() {
+ return valuePredicate;
+ }
+
+ /**
+ * Sets the {@link Predicate} to use to match the context's attribute value.
+ *
+ * @param predicate new {@link Predicate} to use to match the context's attribute value
+ */
+ public void setValuePredicate(@Nonnull final Predicate<CharSequence> predicate) {
+ valuePredicate = Constraint.isNotNull(predicate, "value predicate may not be null");
+ }
+
+ /**
+ * Gets the {@link Predicate} being used to match the context's attribute name.
+ *
+ * @return the {@link Predicate} being used to match the context's attribute name
+ */
+ @Nonnull
+ public Predicate<CharSequence> getNamePredicate() {
+ return namePredicate;
+ }
+
+ /**
+ * Sets the {@link Predicate} to use to match the context's attribute name.
+ *
+ * @param predicate new {@link Predicate} to use to match the context's attribute name
+ */
+ public void setNamePredicate(@Nonnull final Predicate<CharSequence> predicate) {
+ namePredicate = Constraint.isNotNull(predicate, "name predicate may not be null");
+ }
+
+ /**
+ * Gets the {@link Predicate} being used to match the context's attribute name format.
+ *
+ * @return the {@link Predicate} being used to match the context's attribute name format
+ */
+ @Nonnull
+ public Predicate<CharSequence> getNameFormatPredicate() {
+ return nameFormatPredicate;
+ }
+
+ /**
+ * Sets the {@link Predicate} to use to match the context's attribute name format.
+ *
+ * @param predicate new {@link Predicate} to use to match the context's attribute name format
+ */
+ public void setNameFormatPredicate(@Nonnull final Predicate<CharSequence> predicate) {
+ nameFormatPredicate = Constraint.isNotNull(predicate, "name format predicate may not be null");
+ }
+
+ /**
+ * Gets the {@link Predicate} being used to match the context's registration authority.
+ *
+ * @return the {@link Predicate} being used to match the context's registration authority
+ */
+ @Nonnull
+ public Predicate<CharSequence> getRegistrationAuthorityPredicate() {
+ return valuePredicate;
+ }
+
+ /**
+ * Sets the {@link Predicate} to use to match the context's registration authority.
+ *
+ * @param predicate new {@link Predicate} to use to match the context's registration authority
+ */
+ public void setRegistrationAuthorityPredicate(@Nonnull final Predicate<CharSequence> predicate) {
+ registrationAuthorityPredicate = Constraint.isNotNull(predicate,
+ "registration authority predicate may not be null");
+ }
+
+ @Override
+ protected boolean matchAttributeValue(@Nonnull final String inputValue) {
+ return valuePredicate.apply(inputValue);
+ }
+
+ @Override
+ protected boolean matchAttributeName(@Nonnull final String inputName) {
+ return namePredicate.apply(inputName);
+ }
+
+ @Override
+ protected boolean matchAttributeNameFormat(@Nonnull final String inputNameFormat) {
+ return nameFormatPredicate.apply(inputNameFormat);
+ }
+
+ @Override
+ protected boolean matchRegistrationAuthority(@Nullable final String inputRegistrationAuthority) {
+ return registrationAuthorityPredicate.apply(inputRegistrationAuthority);
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcher.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcher.java
new file mode 100644
index 0000000..dd19680
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcher.java
@@ -0,0 +1,58 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.ThreadSafe;
+
+import com.google.common.base.Predicate;
+
+/**
+ * An entity attribute matcher which matches a given registration authority.
+ *
+ * It can match against a specific registration authority, or against the absence of
+ * one.
+ */
+ at ThreadSafe
+public class RegistrationAuthorityMatcher implements Predicate<EntityAttributeContext> {
+
+ /** Registration authority to match against. */
+ @Nullable
+ private final String registrationAuthority;
+
+ /**
+ * Constructor.
+ *
+ * @param regAuth registration authority to match, or <code>null</code>
+ */
+ public RegistrationAuthorityMatcher(@Nullable final String regAuth) {
+ registrationAuthority = regAuth;
+ }
+
+ @Override
+ public boolean apply(@Nonnull final EntityAttributeContext input) {
+ if (registrationAuthority == null) {
+ // match entities *without* a registration authority
+ return null == input.getRegistrationAuthority();
+ } else {
+ return registrationAuthority.equals(input.getRegistrationAuthority());
+ }
+ }
+
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContext.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContext.java
new file mode 100644
index 0000000..545f56d
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContext.java
@@ -0,0 +1,112 @@
+/*
+ * 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.metadata.dom.saml.mdattr;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+/**
+ * A simple immutable implementation of {@link EntityAttributeContext}.
+ */
+public class SimpleEntityAttributeContext implements EntityAttributeContext {
+
+ /** The attribute's value. */
+ @Nonnull
+ private final String value;
+
+ /** The attribute's <code>Name</code>. */
+ @Nonnull
+ private final String name;
+
+ /** The attribute's <code>NameFormat</code>. */
+ @Nonnull
+ private final String nameFormat;
+
+ /** The entity's registration authority, or <code>null</code>. */
+ @Nullable
+ private final String registrationAuthority;
+
+ /**
+ * Constructor.
+ *
+ * @param attributeValue attribute value
+ * @param attributeName attribute <code>Name</code>
+ * @param attributeNameFormat attribute <code>NameFormat</code>
+ * @param registrar entity's registration authority, or <code>null</code>
+ */
+ public SimpleEntityAttributeContext(@Nonnull final String attributeValue,
+ @Nonnull final String attributeName,
+ @Nonnull final String attributeNameFormat,
+ @Nullable final String registrar) {
+ value = Constraint.isNotNull(attributeValue, "value may not be null");
+ name = Constraint.isNotNull(attributeName, "name may not be null");
+ nameFormat = Constraint.isNotNull(attributeNameFormat, "name format may not be null");
+ registrationAuthority = registrar;
+ }
+
+ /**
+ * Shorthand three-argument constructor.
+ *
+ * @param attributeValue attribute value
+ * @param attributeName attribute <code>Name</code>
+ * @param attributeNameFormat attribute <code>NameFormat</code>
+ */
+ public SimpleEntityAttributeContext(@Nonnull final String attributeValue,
+ @Nonnull final String attributeName,
+ @Nonnull final String attributeNameFormat) {
+ this(attributeValue, attributeName, attributeNameFormat, null);
+ }
+
+ @Override
+ public String getRegistrationAuthority() {
+ return registrationAuthority;
+ }
+
+ @Override
+ public String getNameFormat() {
+ return nameFormat;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder b = new StringBuilder();
+ b.append("{v=").append(getValue());
+ b.append(", n=").append(getName());
+ b.append(", f=").append(getNameFormat());
+ b.append(", r=");
+ if (getRegistrationAuthority() == null) {
+ b.append("(none)");
+ } else {
+ b.append(getRegistrationAuthority());
+ }
+ b.append('}');
+ return b.toString();
+ }
+}
diff --git a/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/package-info.java b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/package-info.java
new file mode 100644
index 0000000..4015b89
--- /dev/null
+++ b/aggregator-pipeline/src/main/java/net/shibboleth/metadata/dom/saml/mdattr/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Aggregator classes for the entity attributes specification.
+ */
+package net.shibboleth.metadata.dom.saml.mdattr;
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStageTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStageTest.java
new file mode 100644
index 0000000..6a71d6e
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStageTest.java
@@ -0,0 +1,175 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.shibboleth.metadata.Item;
+import net.shibboleth.metadata.dom.BaseDOMTest;
+import net.shibboleth.metadata.dom.DOMElementItem;
+import net.shibboleth.metadata.dom.saml.mdrpi.RegistrationAuthorityPopulationStage;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+public class EntityAttributeFilteringStageTest extends BaseDOMTest {
+
+ protected EntityAttributeFilteringStageTest() {
+ super(EntityAttributeFilteringStage.class);
+ }
+
+ private Element makeInputDocument() throws Exception {
+ return readXMLData("input.xml");
+ }
+
+ private List<Item<Element>> makeItems(final Element inputElement) throws Exception {
+ final Item<Element> item = new DOMElementItem(inputElement);
+ final List<Item<Element>> items = new ArrayList<>();
+ items.add(item);
+
+ // Extract the registration authority
+ final RegistrationAuthorityPopulationStage ras = new RegistrationAuthorityPopulationStage();
+ ras.setId("id");
+ ras.initialize();
+ ras.execute(items);
+ ras.destroy();
+
+ return items;
+ }
+
+ private List<Item<Element>> makeInputItems() throws Exception {
+ return makeItems(makeInputDocument());
+ }
+
+ @Test
+ public void testNoPredicates() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("keepnone.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testKeepCoC() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(new EntityCategoryMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1"));
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("keepcoc.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testKeepCoCRightRegistrar() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(new EntityCategoryMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1",
+ "http://ukfederation.org.uk"));
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("keepcoc.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testKeepCoCWrongRegistrar() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(new EntityCategoryMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1",
+ "http://not.ukfederation.org.uk"));
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("keepnone.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testKeepCoC2() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(new EntityCategoryMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1"));
+ rules.add(new EntityCategorySupportMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1"));
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("keepcoc2.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testKeepEverything() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(Predicates.<EntityAttributeContext>alwaysTrue());
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("input.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+ @Test
+ public void testBlacklist() throws Exception {
+ final List<Item<Element>> items = makeInputItems();
+ final List<Predicate<EntityAttributeContext>> rules = new ArrayList<>();
+ rules.add(new EntityCategoryMatcher("http://www.geant.net/uri/dataprotection-code-of-conduct/v1",
+ "http://ukfederation.org.uk"));
+
+ final EntityAttributeFilteringStage stage = new EntityAttributeFilteringStage();
+ stage.setId("id");
+ stage.setWhitelisting(false);
+ stage.setRules(rules);
+ stage.initialize();
+ stage.execute(items);
+ stage.destroy();
+
+ final Element result = items.get(0).unwrap();
+ final Element expected = readXMLData("blacklist.xml");
+ assertXMLIdentical(expected, result);
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest.java
new file mode 100644
index 0000000..4b6fb9e
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest.java
@@ -0,0 +1,71 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+
+/**
+ * This is the same as {@link EntityCategoryMatcherTest}, but pulls the matcher beans
+ * from a configured application context. This is just to make sure that Spring can
+ * distinguish between the two constructor signatures propertly, so we don't need an
+ * equivalent for every class under test.
+ */
+ at ContextConfiguration("EntityCategoryMatcherSpringTest-config.xml")
+public class EntityCategoryMatcherSpringTest extends AbstractTestNGSpringContextTests {
+
+ private void test(final boolean expected, final Predicate<EntityAttributeContext> matcher,
+ final EntityAttributeContext context) {
+ Assert.assertEquals(matcher.apply(context), expected, context.toString());
+ }
+
+ @Test
+ public void testNoRA() {
+ final Predicate<EntityAttributeContext> matcher =
+ (Predicate<EntityAttributeContext>)applicationContext.getBean("categoryMatcherNoRA");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "whatever"));
+
+ // context has no RA
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", null));
+ }
+
+ @Test
+ public void testWithRA() {
+ final Predicate<EntityAttributeContext> matcher =
+ (Predicate<EntityAttributeContext>)applicationContext.getBean("categoryMatcherWithRA");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+
+ // context has no RA
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar2"));
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherTest.java
new file mode 100644
index 0000000..e55dba0
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherTest.java
@@ -0,0 +1,60 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+
+public class EntityCategoryMatcherTest {
+
+ private void test(final boolean expected, final Predicate<EntityAttributeContext> matcher,
+ final EntityAttributeContext context) {
+ Assert.assertEquals(matcher.apply(context), expected, context.toString());
+ }
+
+ @Test
+ public void testNoRA() {
+ final Predicate<EntityAttributeContext> matcher = new EntityCategoryMatcher("category");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "whatever"));
+
+ // context has no RA
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", null));
+ }
+
+ @Test
+ public void testWithRA() {
+ final Predicate<EntityAttributeContext> matcher = new EntityCategoryMatcher("category", "registrar");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+
+ // context has no RA
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar2"));
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcherTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcherTest.java
new file mode 100644
index 0000000..e89e5db
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/EntityCategorySupportMatcherTest.java
@@ -0,0 +1,60 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+
+public class EntityCategorySupportMatcherTest {
+
+ private void test(final boolean expected, final Predicate<EntityAttributeContext> matcher,
+ final EntityAttributeContext context) {
+ Assert.assertEquals(matcher.apply(context), expected, context.toString());
+ }
+
+ @Test
+ public void testNoRA() {
+ final Predicate<EntityAttributeContext> matcher = new EntityCategorySupportMatcher("category");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "whatever"));
+
+ // context has no RA
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", null));
+ }
+
+ @Test
+ public void testWithRA() {
+ final Predicate<EntityAttributeContext> matcher = new EntityCategorySupportMatcher("category", "registrar");
+
+ // all four components match
+ test(true, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+
+ // context has no RA
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", null));
+
+ // these matches should fail because one component differs
+ test(false, matcher, new SimpleEntityAttributeContext("category2", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("category", "http://macedir.org/entity-category-support",
+ "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "registrar2"));
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcherTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcherTest.java
new file mode 100644
index 0000000..6e0d72d
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/MultiPredicateMatcherTest.java
@@ -0,0 +1,57 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+
+public class MultiPredicateMatcherTest {
+
+ private final EntityAttributeContext context =
+ new SimpleEntityAttributeContext("valuevalue", "namename", "fmtfmt", "regreg");
+
+ @Test
+ public void testNothing() {
+ final Predicate<EntityAttributeContext> matcher = new MultiPredicateMatcher();
+ Assert.assertTrue(matcher.apply(context));
+ }
+
+ @Test
+ public void setNameFormatPredicate() {
+ final MultiPredicateMatcher matcher = new MultiPredicateMatcher();
+ matcher.setNameFormatPredicate(Predicates.containsPattern("tfm"));
+ Assert.assertTrue(matcher.apply(context));
+ matcher.setNameFormatPredicate(Predicates.containsPattern("xxx"));
+ Assert.assertFalse(matcher.apply(context));
+ }
+
+ @Test
+ public void setNamePredicate() {
+ final MultiPredicateMatcher matcher = new MultiPredicateMatcher();
+ matcher.setNamePredicate(Predicates.containsPattern("ena"));
+ Assert.assertTrue(matcher.apply(context));
+ matcher.setNamePredicate(Predicates.containsPattern("xxx"));
+ Assert.assertFalse(matcher.apply(context));
+ }
+
+ @Test
+ public void setRegistrationAuthorityPredicate() {
+ final MultiPredicateMatcher matcher = new MultiPredicateMatcher();
+ matcher.setRegistrationAuthorityPredicate(Predicates.containsPattern("egr"));
+ Assert.assertTrue(matcher.apply(context));
+ matcher.setRegistrationAuthorityPredicate(Predicates.containsPattern("xxx"));
+ Assert.assertFalse(matcher.apply(context));
+ }
+
+ @Test
+ public void setValuePredicate() {
+ final MultiPredicateMatcher matcher = new MultiPredicateMatcher();
+ matcher.setValuePredicate(Predicates.containsPattern("eva"));
+ Assert.assertTrue(matcher.apply(context));
+ matcher.setValuePredicate(Predicates.containsPattern("xxx"));
+ Assert.assertFalse(matcher.apply(context));
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcherTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcherTest.java
new file mode 100644
index 0000000..f4abeee
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/RegistrationAuthorityMatcherTest.java
@@ -0,0 +1,34 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+
+public class RegistrationAuthorityMatcherTest {
+
+ private void test(final boolean expected, final Predicate<EntityAttributeContext> matcher,
+ final EntityAttributeContext context) {
+ Assert.assertEquals(matcher.apply(context), expected, context.toString());
+ }
+
+ @Test
+ public void testWithRA() {
+ final Predicate<EntityAttributeContext> matcher = new RegistrationAuthorityMatcher("registrar");
+
+ test(true, matcher, new SimpleEntityAttributeContext("a", "b", "c", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("a", "b", "c", "registrar2"));
+ test(false, matcher, new SimpleEntityAttributeContext("a", "b", "c", null));
+ }
+
+ @Test
+ public void testNoRA() {
+ final Predicate<EntityAttributeContext> matcher = new RegistrationAuthorityMatcher(null);
+
+ test(false, matcher, new SimpleEntityAttributeContext("a", "b", "c", "registrar"));
+ test(false, matcher, new SimpleEntityAttributeContext("a", "b", "c", "registrar2"));
+ test(true, matcher, new SimpleEntityAttributeContext("a", "b", "c", null));
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContextTest.java b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContextTest.java
new file mode 100644
index 0000000..e4fe919
--- /dev/null
+++ b/aggregator-pipeline/src/test/java/net/shibboleth/metadata/dom/saml/mdattr/SimpleEntityAttributeContextTest.java
@@ -0,0 +1,40 @@
+
+package net.shibboleth.metadata.dom.saml.mdattr;
+
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class SimpleEntityAttributeContextTest {
+
+ @Test
+ public void testFour() {
+ final EntityAttributeContext ctx = new SimpleEntityAttributeContext("a", "b", "c", "d");
+ Assert.assertEquals(ctx.getValue(), "a");
+ Assert.assertEquals(ctx.getName(), "b");
+ Assert.assertEquals(ctx.getNameFormat(), "c");
+ Assert.assertEquals(ctx.getRegistrationAuthority(), "d");
+ }
+
+ @Test
+ public void testThree() {
+ final EntityAttributeContext ctx = new SimpleEntityAttributeContext("a", "b", "c");
+ Assert.assertEquals(ctx.getValue(), "a");
+ Assert.assertEquals(ctx.getName(), "b");
+ Assert.assertEquals(ctx.getNameFormat(), "c");
+ Assert.assertNull(ctx.getRegistrationAuthority());
+ }
+
+ @Test
+ public void stringFour() {
+ final EntityAttributeContext ctx = new SimpleEntityAttributeContext("a", "b", "c", "d");
+ Assert.assertEquals(ctx.toString(), "{v=a, n=b, f=c, r=d}");
+ }
+
+ @Test
+ public void stringThree() {
+ final EntityAttributeContext ctx = new SimpleEntityAttributeContext("a", "b", "c");
+ Assert.assertEquals(ctx.toString(), "{v=a, n=b, f=c, r=(none)}");
+ }
+
+}
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-blacklist.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-blacklist.xml
new file mode 100644
index 0000000..0e65371
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-blacklist.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
+ xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ entityID="http://example.org/entity">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="http://ukfederation.org.uk"
+ registrationInstant="2014-03-18T15:23:31Z">
+ <mdrpi:RegistrationPolicy xml:lang="en"
+ >http://ukfederation.org.uk/doc/mdrps-20130902</mdrpi:RegistrationPolicy>
+ </mdrpi:RegistrationInfo>
+ <mdattr:EntityAttributes>
+ <saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+
+ <saml:AttributeValue>http://example.org/category2</saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="http://macedir.org/entity-category-support" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml:AttributeValue>http://example.org/category2support</saml:AttributeValue>
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="anotherAttributeName" NameFormat="anotherNameFormat">
+ <saml:AttributeValue>anotherValue</saml:AttributeValue>
+ </saml:Attribute>
+ </mdattr:EntityAttributes>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIEfzCCA2egAwIBAgIQQSSnV5Mk/EXZxgrsbnU7ajANBgkqhkiG9w0BAQUFADA2
+ MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
+ U1NMIENBMB4XDTEzMDMwNjAwMDAwMFoXDTE2MDMwNTIzNTk1OVowRzEhMB8GA1UE
+ CxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMSIwIAYDVQQDExlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+ qzeOIPfgr/SneQUtjqDRGLbG4YKxmo2zfAIF+wjaYXnDTq/yWt852nImchvCgjWu
+ eXnHJ6oZZGdaN4kMgPh1oxqJ4UE6dXY9HEoru/Awp2P/CGiYOQ4Q5u5+AyFznGRx
+ y2uNYrD85C6uTIgiKytH6Lai8f6dFxHKO/u8o+kbrl2Z1CkAf6wePu2H5a44tGnF
+ SP/s7lW4ScSthNz1OF8BoPFKpWUmJk/584rZZjR+fqB9fQBwxRoRBCFZTduXP0G9
+ 861BS6Nt6Dfuli9jdCBC0L8ai4fH43a94EQVmMfcjImrkYBg7v6lVS4IY75ONiOt
+ sObamvbT+yNEuqw0jBjmKwIDAQABo4IBdjCCAXIwHwYDVR0jBBgwFoAUDL2TaAzz
+ 3qujSWsrN1dH6pDjue0wHQYDVR0OBBYEFBQXWZZ8RdkPMtC2o0RF+T+gH7VsMA4G
+ A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAiBgNVHSAEGzAZMA0GCysGAQQBsjEBAgIdMAgGBmeBDAECATA6
+ BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVO
+ QVNTTENBLmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9j
+ cnQudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpo
+ dHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzAkBgNVHREEHTAbghlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MA0GCSqGSIb3DQEBBQUAA4IBAQCRJqxXjeInIqlPLH5+
+ iFqL92oLPKiJDqlDWpzR9P0xF7IS4oBApWZ3f2Rgcx1dtwUf7TakMpAuxIxzMjfP
+ xaik/AuInMjxKU9AJS/lRlLogT3YXZ2aAGZbt2P/hYn4mdn5ryB9WF/w7mnyrpBb
+ o7vllsYXYmRX/c0MEPYfSMoKxomRAY2ViIh83m4sYk8+Nkm+3I9t0O3wBqaQYqpc
+ Mg48AG2JwLeuKUIC+faPOckeMXdrknL0Ra7Vb+eRoEKCqw3L9ka5/rloFNEN+hMZ
+ zubyfY3feeIV+kq3YNmjCwhDqckv5kXAdnkFprjB3X/xNfML2Jum02hKkff4AYfP
+ 2IOi
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://example.org/whatever" index="0" isDefault="true"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-input.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-input.xml
new file mode 100644
index 0000000..dab899a
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-input.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
+ xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ entityID="http://example.org/entity">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="http://ukfederation.org.uk"
+ registrationInstant="2014-03-18T15:23:31Z">
+ <mdrpi:RegistrationPolicy xml:lang="en"
+ >http://ukfederation.org.uk/doc/mdrps-20130902</mdrpi:RegistrationPolicy>
+ </mdrpi:RegistrationInfo>
+ <mdattr:EntityAttributes>
+ <saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+ <saml:AttributeValue>http://example.org/category2</saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="http://macedir.org/entity-category-support" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml:AttributeValue>http://example.org/category2support</saml:AttributeValue>
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+ </saml:Attribute>
+ <saml:Attribute Name="anotherAttributeName" NameFormat="anotherNameFormat">
+ <saml:AttributeValue>anotherValue</saml:AttributeValue>
+ </saml:Attribute>
+ </mdattr:EntityAttributes>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIEfzCCA2egAwIBAgIQQSSnV5Mk/EXZxgrsbnU7ajANBgkqhkiG9w0BAQUFADA2
+ MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
+ U1NMIENBMB4XDTEzMDMwNjAwMDAwMFoXDTE2MDMwNTIzNTk1OVowRzEhMB8GA1UE
+ CxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMSIwIAYDVQQDExlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+ qzeOIPfgr/SneQUtjqDRGLbG4YKxmo2zfAIF+wjaYXnDTq/yWt852nImchvCgjWu
+ eXnHJ6oZZGdaN4kMgPh1oxqJ4UE6dXY9HEoru/Awp2P/CGiYOQ4Q5u5+AyFznGRx
+ y2uNYrD85C6uTIgiKytH6Lai8f6dFxHKO/u8o+kbrl2Z1CkAf6wePu2H5a44tGnF
+ SP/s7lW4ScSthNz1OF8BoPFKpWUmJk/584rZZjR+fqB9fQBwxRoRBCFZTduXP0G9
+ 861BS6Nt6Dfuli9jdCBC0L8ai4fH43a94EQVmMfcjImrkYBg7v6lVS4IY75ONiOt
+ sObamvbT+yNEuqw0jBjmKwIDAQABo4IBdjCCAXIwHwYDVR0jBBgwFoAUDL2TaAzz
+ 3qujSWsrN1dH6pDjue0wHQYDVR0OBBYEFBQXWZZ8RdkPMtC2o0RF+T+gH7VsMA4G
+ A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAiBgNVHSAEGzAZMA0GCysGAQQBsjEBAgIdMAgGBmeBDAECATA6
+ BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVO
+ QVNTTENBLmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9j
+ cnQudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpo
+ dHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzAkBgNVHREEHTAbghlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MA0GCSqGSIb3DQEBBQUAA4IBAQCRJqxXjeInIqlPLH5+
+ iFqL92oLPKiJDqlDWpzR9P0xF7IS4oBApWZ3f2Rgcx1dtwUf7TakMpAuxIxzMjfP
+ xaik/AuInMjxKU9AJS/lRlLogT3YXZ2aAGZbt2P/hYn4mdn5ryB9WF/w7mnyrpBb
+ o7vllsYXYmRX/c0MEPYfSMoKxomRAY2ViIh83m4sYk8+Nkm+3I9t0O3wBqaQYqpc
+ Mg48AG2JwLeuKUIC+faPOckeMXdrknL0Ra7Vb+eRoEKCqw3L9ka5/rloFNEN+hMZ
+ zubyfY3feeIV+kq3YNmjCwhDqckv5kXAdnkFprjB3X/xNfML2Jum02hKkff4AYfP
+ 2IOi
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://example.org/whatever" index="0" isDefault="true"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc.xml
new file mode 100644
index 0000000..5ff0b4a
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
+ xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ entityID="http://example.org/entity">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="http://ukfederation.org.uk"
+ registrationInstant="2014-03-18T15:23:31Z">
+ <mdrpi:RegistrationPolicy xml:lang="en"
+ >http://ukfederation.org.uk/doc/mdrps-20130902</mdrpi:RegistrationPolicy>
+ </mdrpi:RegistrationInfo>
+ <mdattr:EntityAttributes>
+ <saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+
+ </saml:Attribute>
+
+
+ </mdattr:EntityAttributes>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIEfzCCA2egAwIBAgIQQSSnV5Mk/EXZxgrsbnU7ajANBgkqhkiG9w0BAQUFADA2
+ MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
+ U1NMIENBMB4XDTEzMDMwNjAwMDAwMFoXDTE2MDMwNTIzNTk1OVowRzEhMB8GA1UE
+ CxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMSIwIAYDVQQDExlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+ qzeOIPfgr/SneQUtjqDRGLbG4YKxmo2zfAIF+wjaYXnDTq/yWt852nImchvCgjWu
+ eXnHJ6oZZGdaN4kMgPh1oxqJ4UE6dXY9HEoru/Awp2P/CGiYOQ4Q5u5+AyFznGRx
+ y2uNYrD85C6uTIgiKytH6Lai8f6dFxHKO/u8o+kbrl2Z1CkAf6wePu2H5a44tGnF
+ SP/s7lW4ScSthNz1OF8BoPFKpWUmJk/584rZZjR+fqB9fQBwxRoRBCFZTduXP0G9
+ 861BS6Nt6Dfuli9jdCBC0L8ai4fH43a94EQVmMfcjImrkYBg7v6lVS4IY75ONiOt
+ sObamvbT+yNEuqw0jBjmKwIDAQABo4IBdjCCAXIwHwYDVR0jBBgwFoAUDL2TaAzz
+ 3qujSWsrN1dH6pDjue0wHQYDVR0OBBYEFBQXWZZ8RdkPMtC2o0RF+T+gH7VsMA4G
+ A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAiBgNVHSAEGzAZMA0GCysGAQQBsjEBAgIdMAgGBmeBDAECATA6
+ BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVO
+ QVNTTENBLmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9j
+ cnQudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpo
+ dHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzAkBgNVHREEHTAbghlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MA0GCSqGSIb3DQEBBQUAA4IBAQCRJqxXjeInIqlPLH5+
+ iFqL92oLPKiJDqlDWpzR9P0xF7IS4oBApWZ3f2Rgcx1dtwUf7TakMpAuxIxzMjfP
+ xaik/AuInMjxKU9AJS/lRlLogT3YXZ2aAGZbt2P/hYn4mdn5ryB9WF/w7mnyrpBb
+ o7vllsYXYmRX/c0MEPYfSMoKxomRAY2ViIh83m4sYk8+Nkm+3I9t0O3wBqaQYqpc
+ Mg48AG2JwLeuKUIC+faPOckeMXdrknL0Ra7Vb+eRoEKCqw3L9ka5/rloFNEN+hMZ
+ zubyfY3feeIV+kq3YNmjCwhDqckv5kXAdnkFprjB3X/xNfML2Jum02hKkff4AYfP
+ 2IOi
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://example.org/whatever" index="0" isDefault="true"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc2.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc2.xml
new file mode 100644
index 0000000..6be18e8
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepcoc2.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
+ xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ entityID="http://example.org/entity">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="http://ukfederation.org.uk"
+ registrationInstant="2014-03-18T15:23:31Z">
+ <mdrpi:RegistrationPolicy xml:lang="en"
+ >http://ukfederation.org.uk/doc/mdrps-20130902</mdrpi:RegistrationPolicy>
+ </mdrpi:RegistrationInfo>
+ <mdattr:EntityAttributes>
+ <saml:Attribute Name="http://macedir.org/entity-category" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+
+ </saml:Attribute>
+ <saml:Attribute Name="http://macedir.org/entity-category-support" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+
+ <saml:AttributeValue>http://www.geant.net/uri/dataprotection-code-of-conduct/v1</saml:AttributeValue>
+ </saml:Attribute>
+
+ </mdattr:EntityAttributes>
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIEfzCCA2egAwIBAgIQQSSnV5Mk/EXZxgrsbnU7ajANBgkqhkiG9w0BAQUFADA2
+ MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
+ U1NMIENBMB4XDTEzMDMwNjAwMDAwMFoXDTE2MDMwNTIzNTk1OVowRzEhMB8GA1UE
+ CxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMSIwIAYDVQQDExlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+ qzeOIPfgr/SneQUtjqDRGLbG4YKxmo2zfAIF+wjaYXnDTq/yWt852nImchvCgjWu
+ eXnHJ6oZZGdaN4kMgPh1oxqJ4UE6dXY9HEoru/Awp2P/CGiYOQ4Q5u5+AyFznGRx
+ y2uNYrD85C6uTIgiKytH6Lai8f6dFxHKO/u8o+kbrl2Z1CkAf6wePu2H5a44tGnF
+ SP/s7lW4ScSthNz1OF8BoPFKpWUmJk/584rZZjR+fqB9fQBwxRoRBCFZTduXP0G9
+ 861BS6Nt6Dfuli9jdCBC0L8ai4fH43a94EQVmMfcjImrkYBg7v6lVS4IY75ONiOt
+ sObamvbT+yNEuqw0jBjmKwIDAQABo4IBdjCCAXIwHwYDVR0jBBgwFoAUDL2TaAzz
+ 3qujSWsrN1dH6pDjue0wHQYDVR0OBBYEFBQXWZZ8RdkPMtC2o0RF+T+gH7VsMA4G
+ A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAiBgNVHSAEGzAZMA0GCysGAQQBsjEBAgIdMAgGBmeBDAECATA6
+ BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVO
+ QVNTTENBLmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9j
+ cnQudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpo
+ dHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzAkBgNVHREEHTAbghlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MA0GCSqGSIb3DQEBBQUAA4IBAQCRJqxXjeInIqlPLH5+
+ iFqL92oLPKiJDqlDWpzR9P0xF7IS4oBApWZ3f2Rgcx1dtwUf7TakMpAuxIxzMjfP
+ xaik/AuInMjxKU9AJS/lRlLogT3YXZ2aAGZbt2P/hYn4mdn5ryB9WF/w7mnyrpBb
+ o7vllsYXYmRX/c0MEPYfSMoKxomRAY2ViIh83m4sYk8+Nkm+3I9t0O3wBqaQYqpc
+ Mg48AG2JwLeuKUIC+faPOckeMXdrknL0Ra7Vb+eRoEKCqw3L9ka5/rloFNEN+hMZ
+ zubyfY3feeIV+kq3YNmjCwhDqckv5kXAdnkFprjB3X/xNfML2Jum02hKkff4AYfP
+ 2IOi
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://example.org/whatever" index="0" isDefault="true"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepnone.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepnone.xml
new file mode 100644
index 0000000..f4be251
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityAttributeFilteringStage-keepnone.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute"
+ xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi"
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
+ entityID="http://example.org/entity">
+ <Extensions>
+ <mdrpi:RegistrationInfo registrationAuthority="http://ukfederation.org.uk"
+ registrationInstant="2014-03-18T15:23:31Z">
+ <mdrpi:RegistrationPolicy xml:lang="en"
+ >http://ukfederation.org.uk/doc/mdrps-20130902</mdrpi:RegistrationPolicy>
+ </mdrpi:RegistrationInfo>
+
+ </Extensions>
+ <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
+ <KeyDescriptor>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>
+ MIIEfzCCA2egAwIBAgIQQSSnV5Mk/EXZxgrsbnU7ajANBgkqhkiG9w0BAQUFADA2
+ MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
+ U1NMIENBMB4XDTEzMDMwNjAwMDAwMFoXDTE2MDMwNTIzNTk1OVowRzEhMB8GA1UE
+ CxMYRG9tYWluIENvbnRyb2wgVmFsaWRhdGVkMSIwIAYDVQQDExlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
+ qzeOIPfgr/SneQUtjqDRGLbG4YKxmo2zfAIF+wjaYXnDTq/yWt852nImchvCgjWu
+ eXnHJ6oZZGdaN4kMgPh1oxqJ4UE6dXY9HEoru/Awp2P/CGiYOQ4Q5u5+AyFznGRx
+ y2uNYrD85C6uTIgiKytH6Lai8f6dFxHKO/u8o+kbrl2Z1CkAf6wePu2H5a44tGnF
+ SP/s7lW4ScSthNz1OF8BoPFKpWUmJk/584rZZjR+fqB9fQBwxRoRBCFZTduXP0G9
+ 861BS6Nt6Dfuli9jdCBC0L8ai4fH43a94EQVmMfcjImrkYBg7v6lVS4IY75ONiOt
+ sObamvbT+yNEuqw0jBjmKwIDAQABo4IBdjCCAXIwHwYDVR0jBBgwFoAUDL2TaAzz
+ 3qujSWsrN1dH6pDjue0wHQYDVR0OBBYEFBQXWZZ8RdkPMtC2o0RF+T+gH7VsMA4G
+ A1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMB
+ BggrBgEFBQcDAjAiBgNVHSAEGzAZMA0GCysGAQQBsjEBAgIdMAgGBmeBDAECATA6
+ BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLnRjcy50ZXJlbmEub3JnL1RFUkVO
+ QVNTTENBLmNybDBtBggrBgEFBQcBAQRhMF8wNQYIKwYBBQUHMAKGKWh0dHA6Ly9j
+ cnQudGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3J0MCYGCCsGAQUFBzABhhpo
+ dHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzAkBgNVHREEHTAbghlzcDIwMTMtaGEt
+ YWRmczIuZ2VhbnQubmV0MA0GCSqGSIb3DQEBBQUAA4IBAQCRJqxXjeInIqlPLH5+
+ iFqL92oLPKiJDqlDWpzR9P0xF7IS4oBApWZ3f2Rgcx1dtwUf7TakMpAuxIxzMjfP
+ xaik/AuInMjxKU9AJS/lRlLogT3YXZ2aAGZbt2P/hYn4mdn5ryB9WF/w7mnyrpBb
+ o7vllsYXYmRX/c0MEPYfSMoKxomRAY2ViIh83m4sYk8+Nkm+3I9t0O3wBqaQYqpc
+ Mg48AG2JwLeuKUIC+faPOckeMXdrknL0Ra7Vb+eRoEKCqw3L9ka5/rloFNEN+hMZ
+ zubyfY3feeIV+kq3YNmjCwhDqckv5kXAdnkFprjB3X/xNfML2Jum02hKkff4AYfP
+ 2IOi
+ </ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </KeyDescriptor>
+ <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+ Location="https://example.org/whatever" index="0" isDefault="true"/>
+ </SPSSODescriptor>
+</EntityDescriptor>
diff --git a/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest-config.xml b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest-config.xml
new file mode 100644
index 0000000..dbc2480
--- /dev/null
+++ b/aggregator-pipeline/src/test/resources/net/shibboleth/metadata/dom/saml/mdattr/EntityCategoryMatcherSpringTest-config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
+
+ <bean id="categoryMatcherNoRA" class="net.shibboleth.metadata.dom.saml.mdattr.EntityCategoryMatcher">
+ <constructor-arg value="category"/>
+ </bean>
+
+ <bean id="categoryMatcherWithRA" class="net.shibboleth.metadata.dom.saml.mdattr.EntityCategoryMatcher">
+ <constructor-arg value="category"/>
+ <constructor-arg value="registrar"/>
+ </bean>
+
+</beans>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list