diff --git a/doc/RELEASE-NOTES.md b/doc/RELEASE-NOTES.md index 3395236..63843e5 100644 --- a/doc/RELEASE-NOTES.md +++ b/doc/RELEASE-NOTES.md @@ -1,5 +1,10 @@ # Release Notes for `ukf-mda` +## Version 0.10.1 ## + +* Added `StatusMetadataCheckingStrategy`: A strategy for evaluating status metadata against a configurable type and message. +* Added `StatusMetadataFilteringStage`: A stage that removes matching entries from an item's metadata collection based on a configurable type and message. + ## Version 0.10.0 ## * Move to Shibboleth Java 11 platform. diff --git a/src/main/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy.java b/src/main/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy.java new file mode 100644 index 0000000..f57fc82 --- /dev/null +++ b/src/main/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy.java @@ -0,0 +1,90 @@ +/* + * Licensed 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 uk.org.ukfederation.mda; + +import net.shibboleth.metadata.Item; +import net.shibboleth.metadata.StatusMetadata; +import net.shibboleth.shared.primitive.LoggerFactory; +import org.slf4j.Logger; +import org.w3c.dom.Element; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.Immutable; +import java.util.List; +import java.util.function.Predicate; + + + +/** + * A {@link Predicate} implementation that evaluates whether a {@link Item} + * contains {@link StatusMetadata} of a specified {@code statusType} with a matching message. + * + *

The match can be configured as either an exact match or a substring match using + * the {@code exactMatch} flag.

+ */ +@Immutable +public class StatusMetadataCheckingStrategy implements Predicate> { + + /** Logger for this class. */ + private static final @Nonnull Logger LOG = LoggerFactory.getLogger(StatusMetadataCheckingStrategy.class); + + /** The type of {@link StatusMetadata} to evaluate. */ + @Nonnull private final Class statusType; + /** The message to match against status metadata entries. */ + @Nonnull private final String message; + /** + * Whether the message comparison should be exact or partial. + * + *

If {@code true}, an exact string match is required; + * otherwise, a substring match is performed.

+ */ + private final boolean exactMatch; + + + /** + * Constructs a new strategy for evaluating {@link StatusMetadata}. + * + * @param status the type of status metadata to match + * @param statusMessage the message to match against status entries + * @param exactMatching {@code true} for exact message match; {@code false} for substring match + */ + public StatusMetadataCheckingStrategy(@Nonnull final Class status, @Nonnull final String statusMessage, final boolean exactMatching) { + message = statusMessage; + exactMatch = exactMatching; + statusType = status; + } + + + + /** + * Evaluates whether the supplied {@link Item} contains a + * {@link StatusMetadata} entry of the configured type with a matching message. + * + * @param item the metadata item to evaluate (must not be {@code null}) + * @return {@code true} if a matching status entry is found; {@code false} otherwise + */ + @Override + public boolean test(@Nonnull final Item item) { + final List statusList = item.getItemMetadata().get(statusType); + for (StatusMetadata status: statusList) { + final String statusMessage = status.getStatusMessage(); + if ((exactMatch && message.equals(statusMessage) || + (!exactMatch && statusMessage.contains(message)))) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/uk/org/ukfederation/mda/StatusMetadataFilteringStage.java b/src/main/java/uk/org/ukfederation/mda/StatusMetadataFilteringStage.java new file mode 100644 index 0000000..045c0c0 --- /dev/null +++ b/src/main/java/uk/org/ukfederation/mda/StatusMetadataFilteringStage.java @@ -0,0 +1,143 @@ +/* + * Licensed 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 uk.org.ukfederation.mda; + +import net.shibboleth.metadata.*; +import net.shibboleth.metadata.pipeline.AbstractItemMetadataSelectionStage; +import net.shibboleth.metadata.pipeline.Stage; +import net.shibboleth.shared.annotation.constraint.NonnullAfterInit; +import net.shibboleth.shared.annotation.constraint.NonnullElements; +import net.shibboleth.shared.collection.ClassToInstanceMultiMap; +import net.shibboleth.shared.component.ComponentInitializationException; +import net.shibboleth.shared.primitive.LoggerFactory; +import org.slf4j.Logger; + +import javax.annotation.Nonnull; +import javax.annotation.concurrent.GuardedBy; +import javax.annotation.concurrent.ThreadSafe; +import java.util.List; + + +/** + * A {@link Stage} that removes matching {@link StatusMetadata} entries from + * an {@link Item}'s metadata collection. + * + *

During execution, the stage examines all {@link StatusMetadata} instances + * attached to a matching item and compares their status messages against a + * configured message value. Message matching can be performed using either + * exact equality or substring matching, depending on the value of + * {@code exactMatch}.

+ * + *

When a matching {@link StatusMetadata} instance is found, it is removed + * from the item's metadata.

+ * + *

This stage can be used, for example, to remove specific + * {@link net.shibboleth.metadata.InfoStatus}, + * {@link net.shibboleth.metadata.WarningStatus}, or + * {@link net.shibboleth.metadata.ErrorStatus} entries based on their + * associated status message.

+ * + * @param the type of item content processed by this stage + */ +@ThreadSafe +public class StatusMetadataFilteringStage extends AbstractItemMetadataSelectionStage { + + /** Class logger. */ + private static final @Nonnull Logger LOG = LoggerFactory.getLogger(StatusMetadataFilteringStage.class); + + /** The message to match against status metadata entries. */ + @NonnullAfterInit @GuardedBy("this") + private String message; + /** + * Whether the message comparison should be exact or partial. + * + *

If {@code true}, an exact string match is required; + * otherwise, a substring match is performed.

+ */ + private boolean exactMatch; + + + /** + * Sets the message to match against status entries. + * + * @param statusMessage the message to match against status metadata entries. + */ + public synchronized void setMessage(@Nonnull String statusMessage) { + checkSetterPreconditions(); + message = statusMessage; + } + + /** + * Sets whether the message comparison should be exact or partial. + * + * @param exactMatching {@code true} for exact message match; {@code false} for substring match + */ + public void setExactMatch(boolean exactMatching) { + checkSetterPreconditions(); + exactMatch = exactMatching; + } + + /** + * Gets the message to match against status entries. + * @return message + */ + @Nonnull + public final synchronized String getMessage() { + return message; + } + + /** + * Gets whether the message comparison should be exact or partial. + * @return isExactMatch + */ + public final boolean isExactMatch() { + return exactMatch; + } + + @Override + protected synchronized void doInitialize() throws ComponentInitializationException { + super.doInitialize(); + + if (message == null) { + throw new ComponentInitializationException("Unable to initialize " + getId() + + ", message may not be null"); + } + } + + /** + * Removes all matching {@link StatusMetadata} entries from the supplied item. + * + *

A status entry matches when its message satisfies the configured + * matching criteria. Matching entries are removed from the item's metadata + * collection.

+ * + * @param items the full set of items being processed + * @param matchingItem the item whose metadata is being evaluated + * @param matchingMetadata the metadata associated with the matching item + */ + @Override + protected void doExecute(@Nonnull @NonnullElements final List> items, + @Nonnull final Item matchingItem, + @Nonnull @NonnullElements final ClassToInstanceMultiMap matchingMetadata) { + + for (final StatusMetadata statusMetadata : matchingMetadata.values()) { + final String statusMessage = statusMetadata.getStatusMessage(); + if ((isExactMatch() && getMessage().equals(statusMessage) || + (!isExactMatch() && statusMessage.contains(getMessage())))) { + matchingItem.getItemMetadata().remove(statusMetadata); + } + } + } +} diff --git a/src/main/resources/uk/org/ukfederation/mda/beans.xml b/src/main/resources/uk/org/ukfederation/mda/beans.xml index 98c481b..c71af5e 100644 --- a/src/main/resources/uk/org/ukfederation/mda/beans.xml +++ b/src/main/resources/uk/org/ukfederation/mda/beans.xml @@ -48,6 +48,12 @@ + + + + @@ -81,10 +87,10 @@ - + - + diff --git a/src/test/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategyTest.java b/src/test/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategyTest.java new file mode 100644 index 0000000..f19f263 --- /dev/null +++ b/src/test/java/uk/org/ukfederation/mda/StatusMetadataCheckingStrategyTest.java @@ -0,0 +1,149 @@ + +package uk.org.ukfederation.mda; + +import net.shibboleth.metadata.*; +import net.shibboleth.metadata.dom.DOMElementItem; +import net.shibboleth.shared.xml.XMLParserException; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.w3c.dom.Element; + + +public class StatusMetadataCheckingStrategyTest extends BaseDOMTest { + + /** Default invalid code */ + static private final String MESSAGE_CODE = "strip-invalid-sirtfi"; + + /** Constructor sets class under test. */ + public StatusMetadataCheckingStrategyTest() { + super(StatusMetadataCheckingStrategy.class); + } + + + /** + * Test the true case with + * 1) Warning + * 2) Correct message code + * 2) Exact Match = true + * 3) isRemove = false (default) + * + */ + @Test + public void testTrueWithWarningAndCorrectMessageCodeAndExactMatch() throws XMLParserException { + Assert.assertTrue(internalTest(WarningStatus.class, WarningStatus.class, MESSAGE_CODE, true)); + } + + /** + * Test the true case with + * 1) Error + * 2) Correct message code + * 2) Exact Match = true + * 3) isRemove = false (default) + * + */ + @Test + public void testTrueWithErrorAndCorrectMessageCodeAndExactMatch() throws XMLParserException { + Assert.assertTrue(internalTest(ErrorStatus.class, ErrorStatus.class, MESSAGE_CODE, true)); + } + + /** + * Test the true case with + * 1) Info + * 2) Correct message code + * 2) Exact Match = true + * 3) isRemove = false (default) + * + */ + @Test + public void testTrueWithInfoAndCorrectMessageCodeAndExactMatch() throws XMLParserException { + Assert.assertTrue(internalTest(InfoStatus.class, InfoStatus.class, MESSAGE_CODE, true)); + } + + + /** + * Test the false case with + * 1) Error + * 2) Correct message code + * 2) Exact Match = true + * 3) isRemove = false (default) + * + */ + @Test + public void testFalseWithWrongStatusTypeAndCorrectMessageCodeAndExactMatch() throws XMLParserException { + Assert.assertFalse(internalTest(InfoStatus.class, ErrorStatus.class, MESSAGE_CODE, true)); + } + + /** + * Test the false case with + * 1) Warning + * 2) Incorrect message code + * 2) Exact Match = true + * 3) isRemove = false (default) + * + */ + @Test + public void testFalseWithWarningAndIncorrectMessageCodeAndExactMatch() throws XMLParserException { + Assert.assertFalse(internalTest(WarningStatus.class, WarningStatus.class, "WRONG" + MESSAGE_CODE, true)); + } + + /** + * Test the false case with + * 1) Warning + * 2) Correct message code + * 2) Exact Match = false + * 3) isRemove = false (default) + * + */ + @Test + public void testTrueWithWarningAndCorrectMessageCodeAndNotExactMatch() throws XMLParserException { + Assert.assertTrue(internalTest(WarningStatus.class, WarningStatus.class, MESSAGE_CODE, false)); + } + + /** + * Test the false case with + * 1) Warning + * 2) Incorrect message code + * 2) Exact Match = false + * 3) isRemove = false (default) + * + */ + @Test + public void testFalseWithWarningAndCorrectMessageCodeAndNotExactMatch() throws XMLParserException { + Assert.assertFalse(internalTest(WarningStatus.class, WarningStatus.class, "WRONG" + MESSAGE_CODE, false)); + } + + /** + * Internal generalized test + * + * @param actualStatusType + * Type of the actual message status [Info, Warning, Error] + * @param expectedStatusType + * Type of the expected message status [Info, Warning, Error] + * @param expectedMessage + * Expected message to be matched + * @param exactMatch + * True for exact match, false for contain only + * @return + * True if matched + * @throws XMLParserException + */ + private boolean internalTest(final Class actualStatusType, final Class expectedStatusType, + final String expectedMessage, final boolean exactMatch) throws XMLParserException { + // Create a DOM Document with status meta data + final Item dom = new DOMElementItem(readXMLData("sirtfi.xml")); + if (InfoStatus.class.equals(actualStatusType)) { + dom.getItemMetadata().put(new InfoStatus("id", MESSAGE_CODE)); + } else if (WarningStatus.class.equals(actualStatusType)) { + dom.getItemMetadata().put(new WarningStatus("id", MESSAGE_CODE)); + } else if (ErrorStatus.class.equals(actualStatusType)) { + dom.getItemMetadata().put(new ErrorStatus("id", MESSAGE_CODE)); + } + + // Test + final StatusMetadataCheckingStrategy strat = new StatusMetadataCheckingStrategy(expectedStatusType, expectedMessage, exactMatch); + final boolean result = strat.test(dom); + + return result; + } + +} diff --git a/src/test/java/uk/org/ukfederation/mda/StatusMetadataFilteringStageTest.java b/src/test/java/uk/org/ukfederation/mda/StatusMetadataFilteringStageTest.java new file mode 100644 index 0000000..ebfd9ad --- /dev/null +++ b/src/test/java/uk/org/ukfederation/mda/StatusMetadataFilteringStageTest.java @@ -0,0 +1,227 @@ + +package uk.org.ukfederation.mda; + +import net.shibboleth.metadata.*; +import net.shibboleth.metadata.dom.DOMElementItem; +import net.shibboleth.metadata.pipeline.StageProcessingException; +import net.shibboleth.shared.collection.CollectionSupport; +import net.shibboleth.shared.component.ComponentInitializationException; +import net.shibboleth.shared.xml.XMLParserException; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +public class StatusMetadataFilteringStageTest extends BaseDOMTest { + + /** Default invalid code */ + static private final String MESSAGE_CODE = "strip-invalid-sirtfi"; + + /** Constructor sets class under test. */ + public StatusMetadataFilteringStageTest() { + super(StatusMetadataFilteringStage.class); + } + + + /** + * Test single remove + */ + @Test + public void testRemoveFunctionSingle() throws XMLParserException, StageProcessingException, ComponentInitializationException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE)); + final Class targetStatusType = WarningStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 0); + } + + + /** + * Test single remove with other warning message + */ + @Test + public void testRemoveFunctionSingleWithOtherWarningMessage() throws XMLParserException, StageProcessingException, ComponentInitializationException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id2", "ANOTHER WARNING")); + final Class targetStatusType = WarningStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 1); + } + + /** + * Test multiple remove + */ + @Test + public void testRemoveFunctionMultiple() throws XMLParserException, StageProcessingException, ComponentInitializationException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id2", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id3", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id4", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id5", MESSAGE_CODE)); + final Class targetStatusType = WarningStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 0); + } + + /** + * Test multiple remove of Error Type + */ + @Test + public void testRemoveFunctionMultipleError() throws XMLParserException, StageProcessingException, ComponentInitializationException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new ErrorStatus("id", MESSAGE_CODE)); + statusMetadataList.add(new ErrorStatus("id2", MESSAGE_CODE)); + statusMetadataList.add(new ErrorStatus("id3", MESSAGE_CODE)); + statusMetadataList.add(new ErrorStatus("id4", MESSAGE_CODE)); + statusMetadataList.add(new ErrorStatus("id5", MESSAGE_CODE)); + final Class targetStatusType = ErrorStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 0); + } + + /** + * Test multiple remove of Info Type + */ + @Test + public void testRemoveFunctionMultipleInfo() throws XMLParserException, StageProcessingException, ComponentInitializationException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new InfoStatus("id", MESSAGE_CODE)); + statusMetadataList.add(new InfoStatus("id2", MESSAGE_CODE)); + statusMetadataList.add(new InfoStatus("id3", MESSAGE_CODE)); + statusMetadataList.add(new InfoStatus("id4", MESSAGE_CODE)); + statusMetadataList.add(new InfoStatus("id5", MESSAGE_CODE)); + final Class targetStatusType = InfoStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 0); + } + + + + /** + * Test multiple remove with other types of messages + */ + @Test + public void testRemoveFunctionMultipleWithOtherWarningMessage() throws XMLParserException, StageProcessingException, ComponentInitializationException { + + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id2", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id3", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id4", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id5", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id6", "ANOTHER WARNING")); + statusMetadataList.add(new WarningStatus("id7", "ANOTHER WARNING1")); + statusMetadataList.add(new InfoStatus("id8", "ANOTHER WARNING2")); + statusMetadataList.add(new ErrorStatus("id9", "ANOTHER WARNING3")); + final Class targetStatusType = WarningStatus.class; + internalTest(true, statusMetadataList, targetStatusType, 2); + } + + /** + * Test multiple remove with other types of messages, not exact match + */ + @Test + public void testRemoveFunctionMultipleWithOtherWarningMessageNotExactMatch() throws XMLParserException, StageProcessingException, ComponentInitializationException { + + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE + "post")); + statusMetadataList.add(new WarningStatus("id2", "pre" + MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id3", "pre" + MESSAGE_CODE + "post")); + statusMetadataList.add(new WarningStatus("id4", "strip-invalid-TEST-sirtfi")); + statusMetadataList.add(new WarningStatus("id5", MESSAGE_CODE)); + statusMetadataList.add(new WarningStatus("id6", "ANOTHER WARNING")); + statusMetadataList.add(new WarningStatus("id7", "ANOTHER WARNING1")); + statusMetadataList.add(new InfoStatus("id8", "ANOTHER WARNING2")); + statusMetadataList.add(new ErrorStatus("id9", "ANOTHER WARNING3")); + final Class targetStatusType = WarningStatus.class; + internalTest(false, statusMetadataList, targetStatusType, 3); + } + + + + /** + * Executes a parameterized test of {@link StatusMetadataFilteringStage}. + * + *

A {@link DOMElementItem} is created and populated with the supplied + * {@link StatusMetadata} instances. The configured filter stage is then + * executed against the item, and the remaining number of matching + * {@link StatusMetadata} entries is verified.

+ * + * @param exactMatch whether message matching should be performed using exact + * equality ({@code true}) or substring matching ({@code false}) + * @param statusMetadataList the status metadata entries to attach to the test item + * @param targetStatusType the type of {@link StatusMetadata} to be processed + * by the filter stage + * @param result the expected number of {@link StatusMetadata} entries of the + * specified type remaining after execution + * + * @throws XMLParserException if the test metadata document cannot be parsed + * @throws StageProcessingException if stage execution fails + * @throws ComponentInitializationException if the stage cannot be initialized + */ + private void internalTest(final boolean exactMatch, final List statusMetadataList, + final Class targetStatusType, final int result) throws XMLParserException, StageProcessingException, ComponentInitializationException { + // Create a DOM Document with status metadata + final DOMElementItem dom = new DOMElementItem(readXMLData("sirtfi.xml")); + for (final StatusMetadata statusMetadata: statusMetadataList) { + dom.getItemMetadata().put(statusMetadata); + } + // Put the DOM to a List> for Filter Stage to check + final List> items = new ArrayList<>(); + items.add(dom); + + // Test + final StatusMetadataFilteringStage stage = new StatusMetadataFilteringStage<>(); + stage.setMessage(MESSAGE_CODE); + stage.setExactMatch(exactMatch); + stage.setSelectionRequirements(CollectionSupport.setOf(targetStatusType)); + stage.setId("test"); + stage.initialize(); + stage.execute(items); + + Assert.assertEquals(dom.getItemMetadata().get(targetStatusType).size(), result); + } + + + @Test + public void testNoInputMessage() { + Assert.assertThrows(ComponentInitializationException.class, () -> testInputInternal(null, true).initialize()); + } + + @Test + public void testInputNoExactMatch() throws ComponentInitializationException, XMLParserException { + testInputInternal(MESSAGE_CODE, null).initialize(); + } + + @Test + public void testInputNoMessageAndExactMatch() { + Assert.assertThrows(ComponentInitializationException.class, () -> testInputInternal(null, null).initialize()); + } + + private StatusMetadataFilteringStage testInputInternal(final String message, final Boolean exactMatch) throws XMLParserException { + final List statusMetadataList = new ArrayList<>(); + statusMetadataList.add(new WarningStatus("id", MESSAGE_CODE)); + final Class targetStatusType = WarningStatus.class; + + // Create a DOM Document with status metadata + final DOMElementItem dom = new DOMElementItem(readXMLData("sirtfi.xml")); + for (final StatusMetadata statusMetadata: statusMetadataList) { + dom.getItemMetadata().put(statusMetadata); + } + // Put the DOM to a List> for Filter Stage to check + final List> items = new ArrayList<>(); + items.add(dom); + + // Condition + final StatusMetadataFilteringStage stage = new StatusMetadataFilteringStage<>(); + stage.setMessage(message); + if (exactMatch != null) { + stage.setExactMatch(exactMatch); + } + stage.setSelectionRequirements(CollectionSupport.setOf(targetStatusType)); + stage.setId("test"); + + return stage; + } + + +} diff --git a/src/test/resources/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy-sirtfi.xml b/src/test/resources/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy-sirtfi.xml new file mode 100644 index 0000000..f1c1541 --- /dev/null +++ b/src/test/resources/uk/org/ukfederation/mda/StatusMetadataCheckingStrategy-sirtfi.xml @@ -0,0 +1,251 @@ + + + + + + example.org + + + + http://ukfederation.org.uk/doc/mdrps-20130902 + + + + https://refeds.org/sirtfi + + + + + + + + + Test SPSSODescriptor + + + + + + CN=example.org,DC=example,DC=org + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + + + + + + + + + + + + + + + An Example Organization + This is the identity provider for the example.org domain. + https://idp.example.org/images/heads_80x80.jpg + https://idp.example.org/images/heads_100x43.jpg + https://idp.example.org/images/heads_240x104.jpg + + + 192.0.2.0/24 + example.org + geo:105.616257,-10.474895 + + + + + + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + An Example Organization + An Example Organization + http://example.org/ + + + An + Example + mailto:ukfed@example.org + + + An + Example + mailto:ukfed@example.org + + + An + Example + mailto:anexample@example.org + + + An + Example + mailto:anexample@example.org + + diff --git a/src/test/resources/uk/org/ukfederation/mda/StatusMetadataFilteringStage-sirtfi.xml b/src/test/resources/uk/org/ukfederation/mda/StatusMetadataFilteringStage-sirtfi.xml new file mode 100644 index 0000000..f1c1541 --- /dev/null +++ b/src/test/resources/uk/org/ukfederation/mda/StatusMetadataFilteringStage-sirtfi.xml @@ -0,0 +1,251 @@ + + + + + + example.org + + + + http://ukfederation.org.uk/doc/mdrps-20130902 + + + + https://refeds.org/sirtfi + + + + + + + + + Test SPSSODescriptor + + + + + + CN=example.org,DC=example,DC=org + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + + + + + + + + + + + + + + + An Example Organization + This is the identity provider for the example.org domain. + https://idp.example.org/images/heads_80x80.jpg + https://idp.example.org/images/heads_100x43.jpg + https://idp.example.org/images/heads_240x104.jpg + + + 192.0.2.0/24 + example.org + geo:105.616257,-10.474895 + + + + + + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + + + + + + + + + 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 + IrhKy4GrwvGT/y1q8Q== + + + + + + + urn:mace:shibboleth:1.0:nameIdentifier + urn:oasis:names:tc:SAML:2.0:nameid-format:transient + + + An Example Organization + An Example Organization + http://example.org/ + + + An + Example + mailto:ukfed@example.org + + + An + Example + mailto:ukfed@example.org + + + An + Example + mailto:anexample@example.org + + + An + Example + mailto:anexample@example.org + +