[java-sp-server] branch main updated: First cut of AssertingPartyResolver and ported tests.

Scott Cantor cantor.2 at osu.edu
Mon Feb 6 20:17:48 UTC 2023


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-sp-server.

View the commit online:
http://git.shibboleth.net/view/?p=java-sp-server.git;a=commit;h=843be0d4da3a2f1688a5a4bef3d858e1a17d4323

The following commit(s) were added to refs/heads/main by this push:
     new 843be0d  First cut of AssertingPartyResolver and ported tests.
843be0d is described below

commit 843be0d4da3a2f1688a5a4bef3d858e1a17d4323
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Feb 6 15:17:46 2023 -0500

    First cut of AssertingPartyResolver and ported tests.
---
 pom.xml                                            |   1 +
 sp-bom/pom.xml                                     |   7 +
 sp-server-api/pom.xml                              |   7 -
 .../net/shibboleth/sp/config/AssertingParty.java   |  15 +-
 .../sp/config/AssertingPartyResolver.java          |  50 ++++
 .../net/shibboleth/sp/config/CredentialHolder.java |  63 +++++
 sp-server-impl/pom.xml                             |  10 +-
 .../sp/config/impl/BasicAssertingParty.java        | 147 ++++++++++
 .../config/impl/DefaultAssertingPartyResolver.java | 304 +++++++++++++++++++++
 .../shibboleth/sp/config/impl/package-info.java    |  21 ++
 .../sp/config/impl/BasicAssertingPartyTest.java    | 119 ++++++++
 .../impl/DefaultAssertingPartyResolverTest.java    | 154 +++++++++++
 sp-testing/.checkstyle                             |  10 +
 sp-testing/.gitignore                              |   2 +
 {sp-server-api => sp-testing}/pom.xml              |  47 ++--
 .../profile/testing/MockProfileConfiguration.java  |  41 +++
 .../sp/profile/testing/package-info.java           |  22 ++
 17 files changed, 986 insertions(+), 34 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4f58701..525989f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,6 +68,7 @@
         <module>sp-server-impl</module>
         <module>sp-session-api</module>
         <module>sp-session-impl</module>
+        <module>sp-testing</module>
     </modules>
     
     <dependencies>
diff --git a/sp-bom/pom.xml b/sp-bom/pom.xml
index 9ddf6af..4a76d6a 100644
--- a/sp-bom/pom.xml
+++ b/sp-bom/pom.xml
@@ -60,6 +60,13 @@
                 <version>${project.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>sp-testing</artifactId>
+                <version>${project.version}</version>
+                <scope>test</scope>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
     
diff --git a/sp-server-api/pom.xml b/sp-server-api/pom.xml
index 07d2442..63a6a04 100644
--- a/sp-server-api/pom.xml
+++ b/sp-server-api/pom.xml
@@ -24,39 +24,32 @@
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-attribute-resolver-api</artifactId>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-attribute-filter-api</artifactId>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-metadata-api</artifactId>
-            <scope>compile</scope>
         </dependency>
 
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-service</artifactId>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-support</artifactId>
-            <scope>compile</scope>
         </dependency>
         
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-beans</artifactId>
-            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-context</artifactId>
-            <scope>compile</scope>
         </dependency>
 
         <!-- Provided dependencies -->
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingParty.java b/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingParty.java
index b5b9960..d24e1c2 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingParty.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingParty.java
@@ -27,6 +27,7 @@ import org.opensaml.profile.context.ProfileRequestContext;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotLive;
 import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.component.IdentifiedComponent;
 
 /**
  * Package of options exposed for configuring behavior when dealing with particular sources
@@ -34,7 +35,7 @@ import net.shibboleth.shared.annotation.constraint.Unmodifiable;
  * 
  * <p>Historically referred to as a "relying party", renamed for better accuracy.</p>
  */
-public interface AssertingParty {
+public interface AssertingParty extends IdentifiedComponent {
 
     // TODO: This is entirely speculative but I lean toward this being pretty minimal and not
     // particularly connected to the "existing" <RelyingParty> settings/concept in the SP.
@@ -52,4 +53,16 @@ public interface AssertingParty {
     @Nonnull @NonnullElements @NotLive @Unmodifiable Map<String,ProfileConfiguration> getProfileConfigurations(
             @Nullable final ProfileRequestContext profileRequestContext);
 
+    /**
+     * Get the profile configuration, for the asserting party, for the given profile.
+     * 
+     * @param profileRequestContext current profile request context
+     * @param profileId the ID of the profile
+     * 
+     * @return the configuration for the profile or null if the profile ID was null or empty or there is no
+     *         configuration for the given profile
+     */
+    @Nullable public ProfileConfiguration getProfileConfiguration(
+            @Nullable final ProfileRequestContext profileRequestContext, @Nullable final String profileId);
+
 }
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingPartyResolver.java b/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingPartyResolver.java
new file mode 100644
index 0000000..a0aef23
--- /dev/null
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/config/AssertingPartyResolver.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.sp.config;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.criterion.ProfileRequestContextCriterion;
+import org.opensaml.security.config.SecurityConfiguration;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.Resolver;
+
+/**
+ * Interface to a resolution service that identifies the applicable {@link AssertingParty}
+ * instance for a request based on extensible criteria.
+ * 
+ * <p>The {@link ProfileRequestContextCriterion} criterion type MUST be supported; other
+ * types are optional.</p>
+ * 
+ * <p>This service must also expose a default security configuration for supported profiles.</p>
+ */
+public interface AssertingPartyResolver extends Resolver<AssertingParty,CriteriaSet> {
+
+    /**
+     * Return the default security configuration for the profile.
+     * 
+     * @param profileId the profile ID
+     * 
+     * @return the default configuration for the profile
+     */
+    @Nullable SecurityConfiguration getDefaultSecurityConfiguration(@Nonnull @NotEmpty final String profileId);
+
+}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/CredentialHolder.java b/sp-server-api/src/main/java/net/shibboleth/sp/config/CredentialHolder.java
new file mode 100644
index 0000000..efb5770
--- /dev/null
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/config/CredentialHolder.java
@@ -0,0 +1,63 @@
+/*
+ * 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.sp.config;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.security.credential.Credential;
+
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+
+/**
+ * This is a utility class used as an auto-wiring source for collections of
+ * signing and encryption {@link Credential} objects so that other layers of the
+ * system can gain access to the complete set of them.
+ */
+public class CredentialHolder {
+
+    /** Credentials to expose. */
+    @Nonnull @NonnullElements private final List<Credential> credentials;
+    
+    /**
+     * Constructor.
+     *
+     * @param creds credentials to expose to other components
+     */
+    public CredentialHolder(@Nullable @NonnullElements final Collection<Credential> creds) {
+        if (creds != null) {
+            credentials = List.copyOf(creds);
+        } else {
+            credentials = Collections.emptyList();
+        }
+    }
+    
+    /**
+     * Get the credentials to expose to other components.
+     * 
+     * @return credentials to expose
+     */
+    @Nonnull @NonnullElements public Collection<Credential> getCredentials() {
+        return credentials;
+    }
+    
+}
\ No newline at end of file
diff --git a/sp-server-impl/pom.xml b/sp-server-impl/pom.xml
index eb3352f..2a6ab6d 100644
--- a/sp-server-impl/pom.xml
+++ b/sp-server-impl/pom.xml
@@ -69,7 +69,7 @@
             <artifactId>spring-integration-ip</artifactId>
         </dependency>
     
-        <!-- provided dependencies -->
+        <!-- Provided dependencies -->
         <dependency>
             <groupId>${slf4j.groupId}</groupId>
             <artifactId>jcl-over-slf4j</artifactId>
@@ -85,7 +85,15 @@
             <artifactId>jcommander</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <!-- Test Dependencies -->
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sp-testing</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        
         <dependency>
             <groupId>${spring.groupId}</groupId>
             <artifactId>spring-test</artifactId>
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/BasicAssertingParty.java b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/BasicAssertingParty.java
new file mode 100644
index 0000000..90dc6ee
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/BasicAssertingParty.java
@@ -0,0 +1,147 @@
+/*
+ * 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.sp.config.impl;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.sp.config.AssertingParty;
+import net.shibboleth.sp.config.ProfileConfiguration;
+
+/**
+ * Concrete implementation of {@link AssertingParty} interface to support the default implementation of
+ * a Spring-based configuration resolver.
+ */
+public class BasicAssertingParty extends AbstractIdentifiableInitializableComponent implements AssertingParty,
+        Predicate<ProfileRequestContext> {
+
+    /** Lookup function to supply <code>profileConfigurations</code> property. */
+    @Nonnull
+    private Function<ProfileRequestContext,Map<String,ProfileConfiguration>> profileConfigurationsLookupStrategy;
+
+    /** Predicate that must be true for this configuration to be active for a given request. */
+    @Nonnull private Predicate<ProfileRequestContext> activationCondition;
+
+    /** Constructor. */
+    public BasicAssertingParty() {
+        activationCondition = PredicateSupport.alwaysTrue();
+        profileConfigurationsLookupStrategy = FunctionSupport.constant(null);
+    }
+
+    
+    /** {@inheritDoc} */
+    @Nonnull @NonnullElements @Unmodifiable @NotLive public Map<String,ProfileConfiguration> getProfileConfigurations(
+            @Nullable final ProfileRequestContext profileRequestContext) {
+        checkComponentActive();
+        
+        final Map<String,ProfileConfiguration> map = profileConfigurationsLookupStrategy.apply(profileRequestContext);
+        if (map != null) {
+            return CollectionSupport.copyToMap(map);
+        }
+        return CollectionSupport.emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable public ProfileConfiguration getProfileConfiguration(
+            @Nullable final ProfileRequestContext profileRequestContext, @Nullable final String profileId) {
+        checkComponentActive();
+        
+        final String trimmedId = StringSupport.trimOrNull(profileId);
+        if (trimmedId == null) {
+            return null;
+        }
+        
+        final Map<String,ProfileConfiguration> configs = profileConfigurationsLookupStrategy.apply(profileRequestContext);
+        if (configs != null) {
+            return configs.get(trimmedId);
+        }
+        
+        return null;
+    }
+
+    /**
+     * Set the profile configurations for this relying party.
+     * 
+     * @param configs the configurations to set
+     */
+    public void setProfileConfigurations(@Nullable @NonnullElements final Collection<ProfileConfiguration> configs) {
+        checkSetterPreconditions();
+        
+        if (configs == null) {
+            profileConfigurationsLookupStrategy = FunctionSupport.constant(null);
+        } else {
+            final HashMap<String,ProfileConfiguration> map = new HashMap<>();
+            for (final ProfileConfiguration config : configs) {
+                final String trimmedId =
+                        Constraint.isNotNull(StringSupport.trimOrNull(config.getId()),
+                                "ID of profile configuration class " + config.getClass().getName() + " cannot be null");
+                map.put(trimmedId, config);
+            }
+            profileConfigurationsLookupStrategy = FunctionSupport.constant(map);
+        }
+    }
+
+    /**
+     * Set a lookup strategy for the <code>profileConfigurations</code> property.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setProfileConfigurationsLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,Map<String,ProfileConfiguration>> strategy) {
+        checkSetterPreconditions();
+        
+        profileConfigurationsLookupStrategy = Constraint.isNotNull(strategy, "Lookup strategy cannot be null");
+    }
+
+    /**
+     * Set the condition under which the relying party configuration should be active.
+     * 
+     * @param condition the activation condition
+     */
+    public void setActivationCondition(@Nonnull final Predicate<ProfileRequestContext> condition) {
+        checkSetterPreconditions();
+        
+        activationCondition =
+                Constraint.isNotNull(condition, "Relying party configuration activation condition cannot be null");
+    }
+
+    /** {@inheritDoc} */
+    public boolean test(@Nullable final ProfileRequestContext input) {
+        checkComponentActive();
+        
+        return activationCondition.test(input);
+    }
+
+}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolver.java b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolver.java
new file mode 100644
index 0000000..dfdd5ff
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolver.java
@@ -0,0 +1,304 @@
+/*
+ * 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.sp.config.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.criterion.ProfileRequestContextCriterion;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.security.credential.Credential;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.Criterion;
+import net.shibboleth.shared.resolver.ResolverException;
+import net.shibboleth.sp.config.AssertingParty;
+import net.shibboleth.sp.config.AssertingPartyResolver;
+import net.shibboleth.sp.config.CredentialHolder;
+
+/**
+ * Retrieves a per-asserting party configuration for a given profile request based on the
+ * supplied {@link CriteriaSet}.
+ *
+ * <p>Supported {@link Criterion}:</p>
+ * <ul>
+ *  <li>{@link ProfileRequestContextCriterion}</li>
+ * </ul>
+ * 
+ * <p>
+ * Note that this resolver does not permit more than one {@link AssertingParty} with the same ID.
+ * </p>
+ */
+public class DefaultAssertingPartyResolver extends AbstractIdentifiableInitializableComponent
+        implements AssertingPartyResolver {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(DefaultAssertingPartyResolver.class);
+
+    /** Registered relying party configurations. */
+    @Nonnull private List<BasicAssertingParty> assertingParties;
+
+    /** Default asserting party, used if no other verified instance matches. */
+    @NonnullAfterInit private BasicAssertingParty defaultAssertingParty;
+
+    /** The predicate which decides if this request is "verified". */
+    @NonnullAfterInit private Predicate<ProfileRequestContext> verificationPredicate;
+    
+    /** A global default security configuration. */
+    @Nullable private SecurityConfiguration defaultSecurityConfiguration;
+    
+    /** The global list of all configured signing credentials. */
+    @Nonnull private List<Credential> signingCredentials;
+    
+    /** The global list of all configured encryption credentials. */
+    @Nonnull private List<Credential> encryptionCredentials;
+
+    /** Constructor. */
+    public DefaultAssertingPartyResolver() {
+        assertingParties = CollectionSupport.emptyList();
+        signingCredentials = CollectionSupport.emptyList();
+        encryptionCredentials = CollectionSupport.emptyList();
+    }
+    
+    /**
+     * Get an unmodifiable list of verified relying party configurations.
+     * 
+     * @return unmodifiable list of verified relying party configurations
+     */
+    @Nonnull @NonnullElements @Unmodifiable @NotLive public Collection<BasicAssertingParty> getAssertingParties() {
+        return assertingParties;
+    }
+
+    /**
+     * Set the verified relying party configurations.
+     * 
+     * @param configs list of verified relying party configurations
+     */
+    public void setAssertingParties(@Nullable @NonnullElements final Collection<BasicAssertingParty> configs) {
+        checkSetterPreconditions();
+        
+        if (configs != null) {
+            assertingParties = CollectionSupport.copyToList(configs);
+        } else {
+            assertingParties = CollectionSupport.emptyList();
+        }
+    }
+
+    /**
+     * Get the {@link AssertingParty} to use if no other configuration is applicable.
+     * 
+     * @return default configuration
+     */
+    @NonnullAfterInit public BasicAssertingParty getDefaultConfiguration() {
+        return defaultAssertingParty;
+    }
+
+    /**
+     * Set the {@link AssertingParty} to use if no other configuration is applicable.
+     * 
+     * @param configuration default configuration
+     */
+    public void setDefaultConfiguration(@Nonnull final BasicAssertingParty configuration) {
+        checkSetterPreconditions();
+        defaultAssertingParty = Constraint.isNotNull(configuration, "Default AssertingParty cannot be null");
+    }
+
+    /**
+     * Set the global default {@link SecurityConfiguration}.
+     * 
+     * @param config  global default
+     */
+    public void setDefaultSecurityConfiguration(@Nullable final SecurityConfiguration config) {
+        checkSetterPreconditions();
+        defaultSecurityConfiguration = config;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void doInitialize() throws ComponentInitializationException {
+        super.doInitialize();
+
+        final HashSet<String> configIds = new HashSet<>(assertingParties.size());
+        for (final AssertingParty config : assertingParties) {
+            if (configIds.contains(config.getId())) {
+                throw new ComponentInitializationException("Multiple AssertingParty configurations with ID "
+                        + config.getId() + " detected, IDs must be unique.");
+            }
+            configIds.add(config.getId());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull @NonnullElements public Iterable<AssertingParty> resolve(@Nullable final CriteriaSet criteria)
+            throws ResolverException {
+        checkComponentActive();
+
+        final ProfileRequestContext context = getProfileRequestContext(criteria);
+        if (context == null) {
+            return CollectionSupport.emptyList();
+        }
+
+        log.debug("Resolving asserting party configuration");
+
+        final ArrayList<AssertingParty> matches = new ArrayList<>();
+
+        for (final BasicAssertingParty configuration : assertingParties) {
+            log.debug("Checking if asserting party configuration {} is applicable", configuration.getId());
+            if (configuration.test(context)) {
+                log.debug("Asserting party configuration {} is applicable", configuration.getId());
+                matches.add(configuration);
+            } else {
+                log.debug("Asserting party configuration {} is not applicable", configuration.getId());
+            }
+        }
+
+        if (matches.isEmpty()) {
+            log.debug("No matching asserting party configuration applicable, returning default: {}",
+                    getDefaultConfiguration().getId());
+            return CollectionSupport.singleton(getDefaultConfiguration());
+        }
+        return matches;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable public AssertingParty resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+        checkComponentActive();
+
+        final ProfileRequestContext context = getProfileRequestContext(criteria);
+        if (context == null) {
+            return null;
+        }
+        
+        log.debug("Resolving asserting party configuration");
+
+        for (final BasicAssertingParty configuration : assertingParties) {
+            log.debug("Checking if asserting party configuration {} is applicable", configuration.getId());
+            if (configuration.test(context)) {
+                log.debug("Asserting party configuration {} is applicable", configuration.getId());
+                return configuration;
+            }
+            log.debug("Asserting party configuration {} is not applicable", configuration.getId());
+        }
+
+        log.debug("No asserting party configurations applicable, returning default: {}",
+                getDefaultConfiguration().getId());
+        return getDefaultConfiguration();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable public SecurityConfiguration getDefaultSecurityConfiguration(@Nonnull @NotEmpty final String profileId) {
+        return defaultSecurityConfiguration;
+    }
+    
+    /**
+     * Get the list of all configured signing credentials.
+     * 
+     * @return the list of signing credentials
+     */
+    @Nonnull @NonnullElements @Unmodifiable @NotLive public List<Credential> getSigningCredentials() {
+        return signingCredentials;
+    }
+    
+    /**
+     * Set the list of all configured signing credentials.
+     * 
+     * @param credentials the list of signing credentials, may be null
+     */
+    @Autowired
+    @Qualifier("signing")
+    public void setSigningCredentials(
+            @Nullable @NonnullElements final List<CredentialHolder> credentials) {
+        checkSetterPreconditions();
+        
+        if (credentials != null) {
+            signingCredentials = credentials.stream()
+                    .flatMap(h -> h.getCredentials().stream())
+                    .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+        } else {
+            signingCredentials = CollectionSupport.emptyList();
+        }
+    }
+
+    /**
+     * Get the list of all configured encryption credentials.
+     * 
+     * @return the list of encryption credentials
+     */
+    @Nonnull @NonnullElements @Unmodifiable @NotLive public List<Credential> getEncryptionCredentials() {
+        return encryptionCredentials;
+    }
+    
+    /**
+     * Set the list of all configured encryption credentials.
+     * 
+     * @param credentials the list of encryption credentials, may be null
+     */
+    @Autowired
+    @Qualifier("encryption")
+    public void setEncryptionCredentials(
+            @Nullable @NonnullElements final List<CredentialHolder> credentials) {
+        checkSetterPreconditions();
+        
+        if (credentials != null) {
+            encryptionCredentials = credentials.stream()
+                    .flatMap(h -> h.getCredentials().stream())
+                    .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
+        } else {
+            encryptionCredentials = CollectionSupport.emptyList();
+        }
+    }
+    
+    /**
+     * Get the {@link ProfileRequestContext} included in the input criteria, if any.
+     * 
+     * @param criteria input criteria
+     * 
+     * @return embedded profile request context or null
+     */
+    @Nullable private ProfileRequestContext getProfileRequestContext(@Nullable final CriteriaSet criteria) {
+        if (criteria != null) {
+            final ProfileRequestContextCriterion prcCriterion = criteria.get(ProfileRequestContextCriterion.class);
+            if (prcCriterion != null) {
+                return prcCriterion.getProfileRequestContext();
+            }
+        }
+        
+        return null;
+    }
+    
+}
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/package-info.java b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/package-info.java
new file mode 100644
index 0000000..180de26
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/config/impl/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.
+ */
+
+/**
+ * Implementation of SP-specific configuration.
+ */
+package net.shibboleth.sp.config.impl;
\ No newline at end of file
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/BasicAssertingPartyTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/BasicAssertingPartyTest.java
new file mode 100644
index 0000000..1802969
--- /dev/null
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/BasicAssertingPartyTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.sp.config.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.ConstraintViolationException;
+import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.sp.config.ProfileConfiguration;
+import net.shibboleth.sp.profile.testing.MockProfileConfiguration;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/** Unit test for {@link BasicAssertingParty}. */
+ at SuppressWarnings("javadoc")
+public class BasicAssertingPartyTest {
+
+    @Test public void testConstruction() throws ComponentInitializationException {
+        BasicAssertingParty config = new BasicAssertingParty();
+        config.setId("foo");
+        config.initialize();
+        Assert.assertEquals(config.getId(), "foo");
+        Assert.assertTrue(config.getProfileConfigurations(null).isEmpty());
+
+        config = new BasicAssertingParty();
+        config.setId("foo");
+        config.initialize();
+        Assert.assertEquals(config.getId(), "foo");
+        Assert.assertTrue(config.getProfileConfigurations(null).isEmpty());
+
+        ArrayList<ProfileConfiguration> profileConfigs = new ArrayList<>();
+        profileConfigs.add(new MockProfileConfiguration("foo"));
+        profileConfigs.add(new MockProfileConfiguration("bar"));
+
+        config = new BasicAssertingParty();
+        config.setId("foo");
+        config.setProfileConfigurations(profileConfigs);
+        config.initialize();
+        Assert.assertEquals(config.getId(), "foo");
+        Assert.assertEquals(config.getProfileConfigurations(null).size(), 2);
+
+        try {
+            config = new BasicAssertingParty();
+            config.initialize();
+            Assert.fail();
+        } catch (final ComponentInitializationException e) {
+            // expected this
+        }
+
+        try {
+            config = new BasicAssertingParty();
+            config.setId("");
+            config.initialize();
+            Assert.fail();
+        } catch (final ConstraintViolationException e) {
+            // expected this
+        }
+    }
+
+    @Test public void testProfileConfiguration() throws ComponentInitializationException {
+        final ArrayList<ProfileConfiguration> profileConfigs = new ArrayList<>();
+        profileConfigs.add(new MockProfileConfiguration("foo"));
+        profileConfigs.add(new MockProfileConfiguration("bar"));
+
+        final BasicAssertingParty config = new BasicAssertingParty();
+        config.setId("foo");
+        config.setProfileConfigurations(profileConfigs);
+        config.initialize();
+        
+        Assert.assertNotNull(config.getProfileConfiguration(null, "foo"));
+        Assert.assertNotNull(config.getProfileConfiguration(null, "bar"));
+        Assert.assertNull(config.getProfileConfiguration(null, "baz"));
+    }
+
+    @Test public void testIndirectProfileConfiguration() throws ComponentInitializationException {
+        final Map<String,ProfileConfiguration> profileConfigs = new HashMap<>();
+        profileConfigs.put("foo", new MockProfileConfiguration("foo"));
+        profileConfigs.put("bar", new MockProfileConfiguration("bar"));
+
+        BasicAssertingParty config = new BasicAssertingParty();
+        config.setId("foo");
+        config.setProfileConfigurationsLookupStrategy(FunctionSupport.constant(profileConfigs));
+        config.initialize();
+        
+        Assert.assertNotNull(config.getProfileConfiguration(null, "foo"));
+        Assert.assertNotNull(config.getProfileConfiguration(null, "bar"));
+        Assert.assertNull(config.getProfileConfiguration(null, "baz"));
+        
+        config = new BasicAssertingParty();
+        config.setId("foo");
+        config.setProfileConfigurations(profileConfigs.values());
+        config.setProfileConfigurationsLookupStrategy(FunctionSupport.constant(null));
+        config.initialize();
+        
+        Assert.assertNull(config.getProfileConfiguration(null, "foo"));
+        Assert.assertNull(config.getProfileConfiguration(null, "bar"));
+        Assert.assertNull(config.getProfileConfiguration(null, "baz"));
+    }
+
+}
\ No newline at end of file
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolverTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolverTest.java
new file mode 100644
index 0000000..9a2f6aa
--- /dev/null
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/config/impl/DefaultAssertingPartyResolverTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.sp.config.impl;
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.shared.logic.PredicateSupport;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.sp.config.AssertingParty;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.criterion.ProfileRequestContextCriterion;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/** Unit test for {@link DefaultAssertingPartyResolver}. */
+ at SuppressWarnings("javadoc")
+public class DefaultAssertingPartyResolverTest {
+
+    @Test public void testConstruction() throws ComponentInitializationException {
+        final BasicAssertingParty one = new BasicAssertingParty();
+        one.setId("one");
+        one.initialize();
+
+        final BasicAssertingParty two = new BasicAssertingParty();
+        two.setId("two");
+        two.setActivationCondition(PredicateSupport.alwaysFalse());
+        two.initialize();
+
+        final BasicAssertingParty three = new BasicAssertingParty();
+        three.setId("three");
+        three.initialize();
+        
+        final List<BasicAssertingParty> apConfigs = Arrays.asList(one, two, three);
+
+        DefaultAssertingPartyResolver resolver = new DefaultAssertingPartyResolver();
+        resolver.setId("test");
+        resolver.setAssertingParties(apConfigs);
+        Assert.assertEquals(resolver.getId(), "test");
+        Assert.assertEquals(resolver.getAssertingParties().size(), 3);
+
+        resolver = new DefaultAssertingPartyResolver();
+        resolver.setId("test");
+        Assert.assertEquals(resolver.getId(), "test");
+        Assert.assertEquals(resolver.getAssertingParties().size(), 0);
+
+        resolver = new DefaultAssertingPartyResolver();
+        resolver.setId("test");
+        Assert.assertEquals(resolver.getId(), "test");
+        Assert.assertEquals(resolver.getAssertingParties().size(), 0);
+    }
+    
+    @Test public void testDefault() throws Exception {
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        final ProfileRequestContextCriterion crit = new ProfileRequestContextCriterion(prc); 
+
+        final BasicAssertingParty anonRP = new BasicAssertingParty();
+        anonRP.setId("anonRPId");
+        anonRP.initialize();
+        
+        final BasicAssertingParty defaultRP = new BasicAssertingParty();
+        defaultRP.setId("defaultRPId");
+        defaultRP.initialize();
+
+        final DefaultAssertingPartyResolver resolver = new DefaultAssertingPartyResolver();
+        resolver.setId("test");
+        resolver.setDefaultConfiguration(defaultRP);
+        resolver.initialize();
+        
+        final Iterable<AssertingParty> results = resolver.resolve(new CriteriaSet(crit));
+        Assert.assertNotNull(results);
+        
+        final Iterator<AssertingParty> resultItr = results.iterator();        
+        Assert.assertTrue(resultItr.hasNext());
+        Assert.assertSame(resultItr.next(), defaultRP);
+        Assert.assertFalse(resultItr.hasNext());
+        
+        Assert.assertSame(resolver.resolveSingle(new CriteriaSet(crit)), defaultRP);
+    }
+    
+    @Test public void testResolve() throws Exception {
+        final ProfileRequestContext prc = new ProfileRequestContext();
+        final ProfileRequestContextCriterion crit = new ProfileRequestContextCriterion(prc); 
+    
+        final BasicAssertingParty anonRP = new BasicAssertingParty();
+        anonRP.setId("anonRPId");
+        anonRP.initialize();
+        
+        final BasicAssertingParty defaultRP = new BasicAssertingParty();
+        defaultRP.setId("defaultRPId");
+        defaultRP.initialize();
+
+        final BasicAssertingParty one = new BasicAssertingParty();
+        one.setId("one");
+        one.initialize();
+
+        final BasicAssertingParty two = new BasicAssertingParty();
+        two.setId("two");
+        two.setActivationCondition(PredicateSupport.alwaysFalse());
+        two.initialize();
+
+        final BasicAssertingParty three = new BasicAssertingParty();
+        three.setId("three");
+        three.initialize();
+        
+        final List<BasicAssertingParty> apConfigs = Arrays.asList(one, two, three);
+
+        final DefaultAssertingPartyResolver resolver = new DefaultAssertingPartyResolver();
+        resolver.setId("test");
+        resolver.setAssertingParties(apConfigs);
+        resolver.setDefaultConfiguration(defaultRP);
+        resolver.initialize();
+
+        Iterable<AssertingParty> results = resolver.resolve(new CriteriaSet(crit));
+        Assert.assertNotNull(results);
+
+        Iterator<AssertingParty> resultItr = results.iterator();
+        Assert.assertTrue(resultItr.hasNext());
+        Assert.assertSame(resultItr.next(), one);
+        Assert.assertTrue(resultItr.hasNext());
+        Assert.assertSame(resultItr.next(), three);
+        Assert.assertFalse(resultItr.hasNext());
+
+        AssertingParty result = resolver.resolveSingle(new CriteriaSet(crit));
+        Assert.assertSame(result, one);
+
+        results = resolver.resolve(null);
+        Assert.assertNotNull(results);
+
+        resultItr = results.iterator();
+        Assert.assertFalse(resultItr.hasNext());
+
+        result = resolver.resolveSingle(null);
+        Assert.assertNull(result);
+    }
+}
\ No newline at end of file
diff --git a/sp-testing/.checkstyle b/sp-testing/.checkstyle
new file mode 100644
index 0000000..5bae456
--- /dev/null
+++ b/sp-testing/.checkstyle
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
+  <local-check-config name="Shibboleth Checkstyle" location="/java-sp-server/resources/checkstyle.xml" type="project" description="">
+    <additional-data name="protect-config-file" value="false"/>
+  </local-check-config>
+  <fileset name="all" enabled="true" check-config-name="Shibboleth Checkstyle" local="true">
+    <file-match-pattern match-pattern="." include-pattern="true"/>
+  </fileset>
+</fileset-config>
diff --git a/sp-testing/.gitignore b/sp-testing/.gitignore
new file mode 100644
index 0000000..1df25bf
--- /dev/null
+++ b/sp-testing/.gitignore
@@ -0,0 +1,2 @@
+/test-output
+/target
diff --git a/sp-server-api/pom.xml b/sp-testing/pom.xml
similarity index 65%
copy from sp-server-api/pom.xml
copy to sp-testing/pom.xml
index 07d2442..843aa7f 100644
--- a/sp-server-api/pom.xml
+++ b/sp-testing/pom.xml
@@ -9,53 +9,55 @@
         <version>0.0.1-SNAPSHOT</version>
     </parent>
     
-    <artifactId>sp-server-api</artifactId>
-    <description>SP processing hub/service API.</description>
-    <name>Shibboleth SP :: Processing Hub :: Service API</name>
+    <artifactId>sp-testing</artifactId>
+    <name>Shibboleth SP :: Processing Hub :: Testing API</name>
+    <description>Testing APIs for SP components</description>
     <packaging>jar</packaging>
     
     <properties>
         <checkstyle.configLocation>${project.basedir}/../resources/checkstyle.xml</checkstyle.configLocation>
-        <automatic.module.name>net.shibboleth.sp.server</automatic.module.name>
+        <automatic.module.name>net.shibboleth.sp.testing</automatic.module.name>
     </properties>
         
     <dependencies>
         <!-- Compile dependencies -->
         <dependency>
-            <groupId>net.shibboleth</groupId>
-            <artifactId>shib-attribute-resolver-api</artifactId>
-            <scope>compile</scope>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>sp-server-api</artifactId>
+            <version>${project.version}</version>
         </dependency>
+
         <dependency>
-            <groupId>net.shibboleth</groupId>
-            <artifactId>shib-attribute-filter-api</artifactId>
-            <scope>compile</scope>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-security-api</artifactId>
         </dependency>
+
+        <!-- Normally test scope. -->
         <dependency>
-            <groupId>net.shibboleth</groupId>
-            <artifactId>shib-metadata-api</artifactId>
+            <groupId>org.opensaml</groupId>
+            <artifactId>opensaml-testing</artifactId>
             <scope>compile</scope>
         </dependency>
 
         <dependency>
             <groupId>net.shibboleth</groupId>
-            <artifactId>shib-service</artifactId>
-            <scope>compile</scope>
+            <artifactId>shib-support</artifactId>
         </dependency>
         <dependency>
             <groupId>net.shibboleth</groupId>
-            <artifactId>shib-support</artifactId>
-            <scope>compile</scope>
+            <artifactId>shib-testing</artifactId>
         </dependency>
-        
+
+        <!-- Normally test scope. -->
         <dependency>
-            <groupId>${spring.groupId}</groupId>
-            <artifactId>spring-beans</artifactId>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
             <scope>compile</scope>
         </dependency>
+
         <dependency>
             <groupId>${spring.groupId}</groupId>
-            <artifactId>spring-context</artifactId>
+            <artifactId>spring-test</artifactId>
             <scope>compile</scope>
         </dependency>
 
@@ -72,11 +74,6 @@
         </dependency>
         
         <!-- Test Dependencies -->
-        <dependency>
-            <groupId>${spring.groupId}</groupId>
-            <artifactId>spring-test</artifactId>
-            <scope>test</scope>
-        </dependency>
     </dependencies>
 
 </project>
diff --git a/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/MockProfileConfiguration.java b/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/MockProfileConfiguration.java
new file mode 100644
index 0000000..cbc5240
--- /dev/null
+++ b/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/MockProfileConfiguration.java
@@ -0,0 +1,41 @@
+/*
+ * 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.sp.profile.testing;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.config.BasicSecurityConfiguration;
+
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
+import net.shibboleth.sp.config.AbstractProfileConfiguration;
+import net.shibboleth.sp.config.ProfileConfiguration;
+
+/** Mock implementation of {@link ProfileConfiguration}. */
+public class MockProfileConfiguration extends AbstractProfileConfiguration {
+
+    /**
+     * Constructor.
+     * 
+     * @param id ID of this profile
+     */
+    public MockProfileConfiguration(@Nonnull @NotEmpty final String id) {
+        super(id);
+        setSecurityConfiguration(new BasicSecurityConfiguration());
+    }
+    
+}
\ No newline at end of file
diff --git a/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/package-info.java b/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/package-info.java
new file mode 100644
index 0000000..bde6abd
--- /dev/null
+++ b/sp-testing/src/main/java/net/shibboleth/sp/profile/testing/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * Testing utility classes.
+ */
+
+package net.shibboleth.sp.profile.testing;
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list