[java-plugin-shibd] branch main updated: Adjustments to initial design, work on initial abstract flow actions.
Scott Cantor
cantor.2 at osu.edu
Tue May 21 19:27:12 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-plugin-shibd.
View the commit online:
http://git.shibboleth.net/view/?p=java-plugin-shibd.git;a=commit;h=8a3a9e1be0c52feae28f3ebf45c106fbfb7b0f27
The following commit(s) were added to refs/heads/main by this push:
new 8a3a9e1 Adjustments to initial design, work on initial abstract flow actions.
8a3a9e1 is described below
commit 8a3a9e1be0c52feae28f3ebf45c106fbfb7b0f27
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue May 21 15:27:05 2024 -0400
Adjustments to initial design, work on initial abstract flow actions.
---
.../META-INF/net.shibboleth.idp/postconfig.xml | 20 +--
.../idp/flows/sp/abstract/sp-abstract-beans.xml | 34 ++++
.../idp/flows/sp/abstract/sp-abstract-flow.xml | 54 ++++++
.../shibboleth/idp/flows/sp/ping/ping-beans.xml | 33 ----
.../net/shibboleth/idp/flows/sp/ping/ping-flow.xml | 30 ----
.../shibboleth/idp/module/conf/sp/sp.properties | 11 +-
.../net/shibboleth/sp/conf/agents-system.xml | 5 +-
.../src/main/java/net/shibboleth/sp/Agent.java | 10 ++
...ApplicationResolver.java => AgentResolver.java} | 6 +-
.../net/shibboleth/sp/ApplicationCriterion.java | 50 ------
.../shibboleth/sp/context/AgentRequestContext.java | 78 +++++++++
.../sp/{config => context}/package-info.java | 4 +-
.../main/java/net/shibboleth/sp/package-info.java | 7 +-
sp-server-impl/pom.xml | 24 ++-
.../authn/impl/InitializeAgentRequestContext.java | 183 +++++++++++++++++++++
.../shibboleth/sp/authn/impl}/package-info.java | 4 +-
.../java/net/shibboleth/sp/impl/BasicAgent.java | 33 ++++
...tionResolver.java => DefaultAgentResolver.java} | 48 ++----
.../impl/InitializeAgentRequestContextTest.java | 98 +++++++++++
.../shibboleth/sp/testing/MockAgentResolver.java | 74 +++++++++
.../net/shibboleth/sp/testing}/package-info.java | 4 +-
21 files changed, 631 insertions(+), 179 deletions(-)
diff --git a/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index a0c4a20..513bf41 100644
--- a/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/sp-conf-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -14,22 +14,22 @@
default-init-method="initialize" default-destroy-method="destroy">
- <!-- Application reseolver service. -->
+ <!-- Agent reseolver service. -->
- <bean id="shibboleth.sp.ApplicationResolver" parent="shibboleth.ReloadableService"
- c:claz="net.shibboleth.sp.impl.DefaultApplicationResolver"
- p:serviceConfigurations-ref="ExtendedApplicationResolverResources"
- p:failFast="%{sp.service.applications.failFast:%{idp.service.failFast:false}}"
- p:reloadCheckDelay="%{sp.service.applications.checkInterval:PT0S}" />
+ <bean id="shibboleth.AgentResolver" parent="shibboleth.ReloadableService"
+ c:claz="net.shibboleth.sp.impl.DefaultAgentResolver"
+ p:serviceConfigurations-ref="ExtendedAgentResolverResources"
+ p:failFast="%{sp.service.agents.failFast:%{idp.service.failFast:false}}"
+ p:reloadCheckDelay="%{sp.service.agents.checkInterval:PT0S}" />
- <util:list id="shibboleth.DefaultApplicationResolverResources">
+ <util:list id="shibboleth.DefaultAgentResolverResources">
<value>conditional:%{idp.home}/conf/sp/agents.xml</value>
</util:list>
<!-- Auto-append system config files to resource set. -->
- <bean id ="ExtendedApplicationResolverResources" class="net.shibboleth.shared.spring.factory.CombiningListFactoryBean"
- p:firstList="#{getObject('%{sp.service.applications.resources:shibboleth.ApplicationResolverResources}'.trim()) ?:
- getObject('shibboleth.DefaultApplicationResolverResources')}">
+ <bean id ="ExtendedAgentResolverResources" class="net.shibboleth.shared.spring.factory.CombiningListFactoryBean"
+ p:firstList="#{getObject('%{sp.service.agents.resources:shibboleth.AgentResolverResources}'.trim()) ?:
+ getObject('shibboleth.DefaultAgentResolverResources')}">
<property name="secondList">
<util:list >
<value>classpath:/net/shibboleth/sp/conf/agents-system.xml</value>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml
new file mode 100644
index 0000000..49ad8f5
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:c="http://www.springframework.org/schema/c"
+ xmlns:context="http://www.springframework.org/schema/context" 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/context http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+ default-init-method="initialize" default-destroy-method="destroy">
+
+ <bean id="InitializeProfileRequestContext"
+ class="net.shibboleth.idp.profile.impl.InitializeProfileRequestContext" scope="prototype"
+ p:profileId-ref="shibboleth.sp.profileId"
+ p:loggingId-ref="shibboleth.sp.loggingId" />
+
+ <bean id="PopulateMetricContext"
+ class="org.opensaml.profile.action.impl.PopulateMetricContext" scope="prototype"
+ p:counterName="#{getObject('shibboleth.metrics.ProfileCounter')}"
+ p:metricStrategy="#{getObject('shibboleth.metrics.MetricStrategy')}" />
+
+ <bean id="FlowStartPopulateAuditContext" parent="shibboleth.AbstractPopulateAuditContext"
+ p:fieldExtractors="#{getObject('shibboleth.FlowStartAuditExtractors') ?: getObject('shibboleth.DefaultFlowStartAuditExtractors')}" />
+
+ <bean id="LogEvent" class="org.opensaml.profile.action.impl.LogEvent" scope="prototype"
+ p:suppressedEvents="#{getObject('shibboleth.SuppressedEvents') ?: getObject('shibboleth.DefaultSuppressedEvents')}">
+ <property name="eventContextLookupStrategy">
+ <bean class="net.shibboleth.idp.profile.context.navigate.WebFlowCurrentEventLookupFunction" />
+ </property>
+ </bean>
+
+ <bean id="ExtractUsernamePasswordFromBasicAuth"
+ class="net.shibboleth.idp.authn.impl.ExtractUsernamePasswordFromBasicAuth" scope="prototype"
+ p:httpServletRequestSupplier-ref="shibboleth.HttpServletRequestSupplier" />
+
+</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-flow.xml
new file mode 100644
index 0000000..47c2b43
--- /dev/null
+++ b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-flow.xml
@@ -0,0 +1,54 @@
+<flow xmlns="http://www.springframework.org/schema/webflow"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd"
+ abstract="true">
+
+ <action-state id="AuthenticationSetup">
+ <on-entry>
+ <!-- Needed to allow reuse of various classes. -->
+ <evaluate expression="opensamlProfileRequestContext.ensureSubcontext(T(net.shibboleth.idp.authn.context.AuthenticationContext))" />
+ </on-entry>
+ <evaluate expression="ExtractUsernamePasswordFromBasicAuth" />
+ <evaluate expression="InitializeAgentRequestContext" />
+ <evaluate expression="ValidateAgentAddress" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="DoCachedAuthentication" />
+ </action-state>
+
+ <action-state id="DoCachedAuthentication">
+ <evaluate expression="ValidateCachedAuthentication" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="DecodeMessage" />
+ <transition on="NoCredentials" to="DoAuthentication" />
+ </action-state>
+
+ <action-state id="DoAuthentication">
+ <evaluate expression="ValidateCredentials" />
+ <evaluate expression="FinalizeAuthentication" />
+ <evaluate expression="'proceed'" />
+
+ <transition on="proceed" to="DecodeMessage" />
+ </action-state>
+
+ <!-- Passthrough state if an exception is thrown. -->
+ <action-state id="LogRuntimeException">
+ <on-entry>
+ <evaluate
+ expression="T(org.slf4j.LoggerFactory).getLogger('net.shibboleth.sp.profile').error('Uncaught runtime exception', flowExecutionException.getCause())" />
+ </on-entry>
+ <evaluate expression="'RuntimeException'" />
+ <transition to="HandleError" />
+ </action-state>
+
+ <!-- All unhandled non-proceed results are turned into errors. -->
+ <global-transitions>
+ <transition on-exception="java.lang.RuntimeException" to="LogRuntimeException" />
+ <transition on="#{!'proceed'.equals(currentEvent.id)}" to="HandleError" />
+ </global-transitions>
+
+ <!-- The file really exists in this directory, but it's referenced from extending flow-directories -->
+ <bean-import resource="classpath:/META-INF/net/shibboleth/idp/flows/sp/abstract/sp-abstract-beans.xml" />
+
+</flow>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-beans.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-beans.xml
deleted file mode 100644
index c8d5026..0000000
--- a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-beans.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans
- xmlns="http://www.springframework.org/schema/beans"
- xmlns:c="http://www.springframework.org/schema/c"
- xmlns:context="http://www.springframework.org/schema/context"
- 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/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
- default-init-method="initialize"
- default-destroy-method="destroy">
-
- <!-- Profile ID for flow. -->
- <bean id="shibboleth.ProfileId" class="java.lang.String" c:_0="http://shibboleth.net/ns/profiles/sp/echo" />
-
- <!-- Profile counter name. -->
-<!-- <bean id="shibboleth.metrics.ProfileCounter" class="java.lang.String" c:_0="net.shibboleth.sp.profiles.echo" />-->
-
- <bean id="InitializeProfileRequestContext"
- class="net.shibboleth.idp.profile.impl.InitializeProfileRequestContext" scope="prototype"
- p:profileId-ref="shibboleth.ProfileId" />
-
- <!-- Work beans. -->
-
- <bean id="DoPing" class="net.shibboleth.sp.profile.impl.DoPing" scope="prototype"
- p:httpServletResponseSupplier-ref="shibboleth.HttpServletResponseSupplier" />
-
- <bean id="RecordResponseComplete" class="net.shibboleth.idp.profile.impl.RecordResponseComplete" scope="prototype" />
-
-
-</beans>
diff --git a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-flow.xml b/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-flow.xml
deleted file mode 100644
index 3950542..0000000
--- a/sp-conf-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/sp/ping/ping-flow.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<flow xmlns="http://www.springframework.org/schema/webflow"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow.xsd">
-
- <!-- Start action. -->
-
- <action-state id="InitializeProfileRequestContext">
- <evaluate expression="InitializeProfileRequestContext" />
- <evaluate expression="'proceed'" />
-
- <transition on="proceed" to="DoProfileWork" />
- </action-state>
-
- <!-- Resume actual flow processing. -->
-
- <action-state id="DoProfileWork">
- <evaluate expression="DoPing" />
- <evaluate expression="RecordResponseComplete" />
- <evaluate expression="'proceed'" />
-
- <transition on="proceed" to="end" />
- </action-state>
-
- <!-- Terminus -->
-
- <end-state id="end" />
-
- <bean-import resource="ping-beans.xml" />
-
-</flow>
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
index 705abcb..3f3c11b 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/idp/module/conf/sp/sp.properties
@@ -1,8 +1,8 @@
-# Controls configuration of new "SP" service.
+# Controls configuration of service to resolve SP agents.
# Uncomment and define to override service resources
-#sp.service.applications.resources = shibboleth.ApplicationResolverResources
-#sp.service.applications.failFast = false
-sp.service.applications.checkInterval = PT5M
+#sp.service.agents.resources = shibboleth.AgentResolverResources
+#sp.service.agents.failFast = false
+sp.service.agents.checkInterval = PT5M
# General SP cookie properties (maxAge only applies to persistent cookies)
#sp.cookie.secure = true
@@ -20,3 +20,6 @@ sp.encryption.key = %{idp.home}/credentials/sp/sp-encryption.key
sp.encryption.cert = %{idp.home}/credentials/sp/sp-encryption.crt
#sp.encryption.key.2 = %{idp.home}/credentials/sp/sp-encryption-old.key
#sp.encryption.cert.2 = %{idp.home}/credentials/sp/sp-encryption-old.crt
+
+# Set to Basic to require shared secret authentication
+#sp.agent.authentication = None
diff --git a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
index de13a90..38da7b3 100644
--- a/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
+++ b/sp-conf-impl/src/main/resources/net/shibboleth/sp/conf/agents-system.xml
@@ -16,11 +16,12 @@
<context:annotation-config />
<!-- Exposes auto-wired map of Agents. -->
- <bean id="shibboleth.ApplicationResolver" class="net.shibboleth.sp.impl.DefaultApplicationResolver" />
+ <bean id="shibboleth.AgentResolver" class="net.shibboleth.sp.impl.DefaultAgentResolver" />
<!-- Parent beans for Agents and Applications. -->
- <bean id="shibboleth.Agent" class="net.shibboleth.sp.impl.BasicAgent" abstract="true" />
+ <bean id="shibboleth.Agent" class="net.shibboleth.sp.impl.BasicAgent" abstract="true"
+ p:allowedAddressRanges="#{{ '127.0.0.1/32', '::1/128' }}" />
<bean id="shibboleth.Application" class="net.shibboleth.sp.impl.BasicApplication" abstract="true"
p:metadataResolver-ref="shibboleth.MetadataResolverService"
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/Agent.java b/sp-server-api/src/main/java/net/shibboleth/sp/Agent.java
index 7985473..d7680f4 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/Agent.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/Agent.java
@@ -16,6 +16,7 @@
package net.shibboleth.sp;
import java.util.Collection;
+import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -25,6 +26,7 @@ import org.opensaml.profile.context.ProfileRequestContext;
import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.component.IdentifiedComponent;
+import net.shibboleth.shared.net.IPRange;
/**
* Represents a deployment of an SP "agent", the stub that operates in a web server or application
@@ -36,6 +38,14 @@ import net.shibboleth.shared.component.IdentifiedComponent;
@ThreadSafe
public interface Agent extends IdentifiedComponent {
+ /**
+ * Get the network addresses or ranges of addresses from which requests from this agent may
+ * originate.
+ *
+ * @return set of address ranges
+ */
+ @Nonnull Set<IPRange> getAllowedAddressRanges();
+
/**
* Get the issuer value to use in various identity protocols when identifying this agent.
*
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/ApplicationResolver.java b/sp-server-api/src/main/java/net/shibboleth/sp/AgentResolver.java
similarity index 80%
rename from sp-server-api/src/main/java/net/shibboleth/sp/ApplicationResolver.java
rename to sp-server-api/src/main/java/net/shibboleth/sp/AgentResolver.java
index 17e8c0a..54b967f 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/ApplicationResolver.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/AgentResolver.java
@@ -18,12 +18,12 @@ import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.resolver.Resolver;
/**
- * Interface to a resolution service that identifies the target {@link Application}
+ * Interface to a resolution service that identifies the target {@link Agent}
* for a request based on extensible criteria.
*
- * <p>The {@link AgentCriterion} {@link ApplicationCriterion} criterion types MUST be supported; other
+ * <p>The {@link AgentCriterion} criterion type MUST be supported; other
* types are optional.</p>
*/
-public interface ApplicationResolver extends Resolver<Application,CriteriaSet> {
+public interface AgentResolver extends Resolver<Agent,CriteriaSet> {
}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/ApplicationCriterion.java b/sp-server-api/src/main/java/net/shibboleth/sp/ApplicationCriterion.java
deleted file mode 100644
index f9fda54..0000000
--- a/sp-server-api/src/main/java/net/shibboleth/sp/ApplicationCriterion.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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 net.shibboleth.sp;
-
-import javax.annotation.Nonnull;
-
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.StringSupport;
-import net.shibboleth.shared.resolver.Criterion;
-
-/**
- * Resolver {@link Criterion} identifying an application.
- */
-public class ApplicationCriterion implements Criterion {
-
- /** Application ID. */
- @Nonnull @NotEmpty final String applicationId;
-
- /**
- * Constructor.
- *
- * @param id application ID
- */
- public ApplicationCriterion(@Nonnull @NotEmpty final String id) {
- applicationId = Constraint.isNotNull(StringSupport.trimOrNull(id), "Application ID cannot be null or empty");
- }
-
- /**
- * Get the application ID specified.
- *
- * @return application ID
- */
- @Nonnull @NotEmpty public String getId() {
- return applicationId;
- }
-
-}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/context/AgentRequestContext.java b/sp-server-api/src/main/java/net/shibboleth/sp/context/AgentRequestContext.java
new file mode 100644
index 0000000..2b575b9
--- /dev/null
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/context/AgentRequestContext.java
@@ -0,0 +1,78 @@
+/*
+ * 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 net.shibboleth.sp.context;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.messaging.context.BaseContext;
+
+import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.Application;
+
+/**
+ * General context for an agent request tracking basic information about the request.
+ */
+public class AgentRequestContext extends BaseContext {
+
+ /** Agent making the request. */
+ @Nullable private Agent agent;
+
+ /** Application for which the request was made. */
+ @Nullable private Application application;
+
+ /**
+ * Get the agent making the request.
+ *
+ * @return the agent
+ */
+ @Nullable public Agent getAgent() {
+ return agent;
+ }
+
+ /**
+ * Set the agent making the request.
+ *
+ * @param a agent to set
+ *
+ * @return this context
+ */
+ @Nonnull public AgentRequestContext setAgent(Agent a) {
+ agent = a;
+ return this;
+ }
+
+ /**
+ * Get the application for which the request was made.
+ *
+ * @return the application
+ */
+ @Nullable public Application getApplication() {
+ return application;
+ }
+
+ /**
+ * Set the application for which the request was made.
+ *
+ * @param app application to set
+ *
+ * @return this context
+ */
+ @Nonnull public AgentRequestContext setApplication(Application app) {
+ application = app;
+ return this;
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java b/sp-server-api/src/main/java/net/shibboleth/sp/context/package-info.java
similarity index 80%
copy from sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
copy to sp-server-api/src/main/java/net/shibboleth/sp/context/package-info.java
index 61ef139..4650a66 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/context/package-info.java
@@ -13,6 +13,6 @@
*/
/**
- * Core configuration interfaces and classes.
+ * General {@link org.opensaml.messaging.context.BaseContext} subclasses defined by the SP plugin.
*/
-package net.shibboleth.sp.config;
\ No newline at end of file
+package net.shibboleth.sp.context;
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/package-info.java b/sp-server-api/src/main/java/net/shibboleth/sp/package-info.java
index dd814b6..b7543b4 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/package-info.java
+++ b/sp-server-api/src/main/java/net/shibboleth/sp/package-info.java
@@ -13,7 +13,10 @@
*/
/**
- * Core APIs for the SP.
+ * Core APIs for the SP plugin.
*/
-package net.shibboleth.sp;
\ No newline at end of file
+ at NonnullElements
+package net.shibboleth.sp;
+
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
diff --git a/sp-server-impl/pom.xml b/sp-server-impl/pom.xml
index 39257db..5caa179 100644
--- a/sp-server-impl/pom.xml
+++ b/sp-server-impl/pom.xml
@@ -28,11 +28,15 @@
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>${idp.groupId}</groupId>
+ <artifactId>idp-authn-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${idp.groupId}</groupId>
<artifactId>idp-profile-api</artifactId>
- <version>${idp.version}</version>
- <scope>compile</scope>
+ <scope>provided</scope>
</dependency>
<!-- Provided dependencies -->
@@ -67,6 +71,16 @@
<artifactId>opensaml-core-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>${opensaml.groupId}</groupId>
+ <artifactId>opensaml-messaging-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${opensaml.groupId}</groupId>
+ <artifactId>opensaml-profile-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-xmlsec-api</artifactId>
@@ -113,6 +127,12 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>${idp.groupId}</groupId>
+ <artifactId>idp-testing</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>${spring.groupId}</groupId>
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java
new file mode 100644
index 0000000..03b2583
--- /dev/null
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContext.java
@@ -0,0 +1,183 @@
+/*
+ * 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 net.shibboleth.sp.authn.impl;
+
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.action.ActionSupport;
+import org.opensaml.profile.action.EventIds;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+
+import net.shibboleth.idp.authn.AbstractAuthenticationAction;
+import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernamePasswordContext;
+import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeExec;
+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.ResolverException;
+import net.shibboleth.shared.service.ReloadableService;
+import net.shibboleth.shared.service.ServiceException;
+import net.shibboleth.shared.service.ServiceableComponent;
+import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.AgentCriterion;
+import net.shibboleth.sp.AgentResolver;
+import net.shibboleth.sp.context.AgentRequestContext;
+
+/**
+ * An authentication action that relies on extracted HTTP authentication credentials
+ * to resolve the appropriate {@link Agent} and create an {@link AgentRequestContext}.
+ *
+ * @event {@link EventIds#PROCEED_EVENT_ID}
+ * @event {@link EventIds#INVALID_PROFILE_CTX}
+ * @event {@link EventIds#IO_ERROR}
+ * @event {@link AuthnEventIds#UNKNOWN_USERNAME}
+ * @pre <pre>ProfileRequestContext.getSubcontext(AuthenticationContext.class) != null</pre>
+ * @post <pre>ProfileRequestContext.ensureSubcontext(AgentRequestContext.class).getAgent() != null</pre>
+ */
+public class InitializeAgentRequestContext extends AbstractAuthenticationAction {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(InitializeAgentRequestContext.class);
+
+ /** Lookup strategy for {@link UsernamePasswordContext}. */
+ @Nonnull private Function<ProfileRequestContext,UsernamePasswordContext> usernamePasswordContextLookupStrategy;
+
+ /** Creation strategy for {@link AgentRequestContext}. */
+ @Nonnull private Function<ProfileRequestContext,AgentRequestContext> agentRequestContextCreationStrategy;
+
+ /** The agent resolver. */
+ @NonnullAfterInit ReloadableService<AgentResolver> agentResolver;
+
+ /** Cached agent ID from "username". */
+ @NonnullBeforeExec private String agentId;
+
+ /** Constructor. */
+ @SuppressWarnings("null")
+ public InitializeAgentRequestContext() {
+ usernamePasswordContextLookupStrategy = new ChildContextLookup<>(UsernamePasswordContext.class).compose(
+ new ChildContextLookup<>(AuthenticationContext.class));
+ agentRequestContextCreationStrategy = new ChildContextLookup<>(AgentRequestContext.class, true);
+ }
+
+ /**
+ * Sets the lookup strategy for the {@link UsernamePasswordContext}.
+ *
+ * @param strategy lookup strategy
+ */
+ public void setUsernamePasswordContextLookupStrategy(
+ @Nonnull final Function<ProfileRequestContext,UsernamePasswordContext> strategy) {
+ checkSetterPreconditions();
+
+ usernamePasswordContextLookupStrategy = Constraint.isNotNull(strategy,
+ "UsernamePasswordContext lookup strategy cannot be null");
+ }
+
+ /**
+ * Sets the creation strategy for the {@link AgentRequestContext}.
+ *
+ * @param strategy creation strategy
+ */
+ public void setAgentRequestContextCreationStrategy(
+ @Nonnull final Function<ProfileRequestContext,AgentRequestContext> strategy) {
+ checkSetterPreconditions();
+
+ agentRequestContextCreationStrategy = Constraint.isNotNull(strategy,
+ "AgentRequestContext creation strategy cannot be null");
+ }
+
+ /**
+ * Sets the {@link AgentResolver} service to use.
+ *
+ * @param service the {@link AgentResolver} service
+ */
+ public void setAgentResolver(@Nonnull final ReloadableService<AgentResolver> service) {
+ checkSetterPreconditions();
+
+ agentResolver = Constraint.isNotNull(service, "AgentResolver service cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doInitialize() throws ComponentInitializationException {
+ if (agentResolver == null) {
+ throw new ComponentInitializationException("AgentResolver service cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected boolean doPreExecute(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthenticationContext authenticationContext) {
+
+ if (!super.doPreExecute(profileRequestContext, authenticationContext)) {
+ return false;
+ }
+
+ final UsernamePasswordContext usernamePasswordContext =
+ usernamePasswordContextLookupStrategy.apply(profileRequestContext);
+ if (usernamePasswordContext != null) {
+ agentId = usernamePasswordContext.getUsername();
+ }
+
+ if (agentId == null) {
+ ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.UNKNOWN_USERNAME);
+ return false;
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext,
+ @Nonnull final AuthenticationContext authenticationContext) {
+
+ try (final ServiceableComponent<AgentResolver> resolver = agentResolver.getServiceableComponent()) {
+
+ final Agent agent = resolver.getComponent().resolveSingle(new CriteriaSet(new AgentCriterion(agentId)));
+ if (agent == null) {
+ log.warn("{} Unknown agent: '{}'", getLogPrefix(), agentId);
+ ActionSupport.buildEvent(profileRequestContext, AuthnEventIds.UNKNOWN_USERNAME);
+ return;
+ }
+
+ final AgentRequestContext agentRequestContext =
+ agentRequestContextCreationStrategy.apply(profileRequestContext);
+ if (agentRequestContext == null) {
+ log.error("{} Unable to create AgentRequestContext", getLogPrefix());
+ ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_PROFILE_CTX);
+ return;
+ }
+
+ agentRequestContext.setAgent(agent);
+
+ } catch (final ServiceException e) {
+ log.error("{} Unable to obtain AgentResolver component", getLogPrefix(), e);
+ ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
+ } catch (final ResolverException e) {
+ log.error("{} Error resolving Agent '{}'", getLogPrefix(), agentId, e);
+ ActionSupport.buildEvent(profileRequestContext, EventIds.IO_ERROR);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/package-info.java
similarity index 85%
copy from sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
copy to sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/package-info.java
index 61ef139..e0b3fcd 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/authn/impl/package-info.java
@@ -13,6 +13,6 @@
*/
/**
- * Core configuration interfaces and classes.
+ * Classes implementing authentication of agent requests.
*/
-package net.shibboleth.sp.config;
\ No newline at end of file
+package net.shibboleth.sp.authn.impl;
\ No newline at end of file
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicAgent.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicAgent.java
index a3073ad..84d1b29 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicAgent.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/BasicAgent.java
@@ -15,6 +15,7 @@
package net.shibboleth.sp.impl;
+import java.net.InetAddress;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
@@ -35,6 +36,7 @@ import net.shibboleth.shared.annotation.constraint.NotEmpty;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.logic.FunctionSupport;
+import net.shibboleth.shared.net.IPRange;
import net.shibboleth.sp.Agent;
import net.shibboleth.sp.Application;
@@ -43,6 +45,9 @@ import net.shibboleth.sp.Application;
*/
public class BasicAgent extends DefaultRelyingPartyConfigurationResolver implements Agent {
+ /** Allowed address ranges. */
+ @Nonnull private Set<IPRange> allowedAddressRanges;
+
/** Application map. */
@Nonnull private Map<String,Application> applicationMap;
@@ -51,9 +56,37 @@ public class BasicAgent extends DefaultRelyingPartyConfigurationResolver impleme
/** Constructor. */
public BasicAgent() {
+ allowedAddressRanges = CollectionSupport.emptySet();
applicationMap = CollectionSupport.emptyMap();
issuerLookupStrategy = FunctionSupport.constant(null);
}
+
+ /** {@inheritDoc} */
+ @Nonnull public Set<IPRange> getAllowedAddressRanges() {
+ return allowedAddressRanges;
+ }
+
+ /**
+ * Set the network ranges from which this agent may make requests.
+ *
+ * @param ranges allowed ranges
+ */
+ public void setAllowedAddressRanges(@Nullable final Set<IPRange> ranges) {
+ checkSetterPreconditions();
+
+ allowedAddressRanges = ranges != null ? CollectionSupport.copyToSet(ranges) : CollectionSupport.emptySet();
+ }
+
+ /**
+ * Returns true iff the supplied address matches one of the allowed ranges.
+ *
+ * @param address address to test
+ *
+ * @return true iff the supplied address matches one of the allowed ranges
+ */
+ public boolean isAllowed(@Nonnull final InetAddress address) {
+ return allowedAddressRanges.stream().anyMatch(r -> r.contains(address));
+ }
/** {@inheritDoc} */
@Nullable @NotEmpty public String getIssuer(@Nullable final ProfileRequestContext profileRequestContext) {
diff --git a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultApplicationResolver.java b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultAgentResolver.java
similarity index 58%
rename from sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultApplicationResolver.java
rename to sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultAgentResolver.java
index adc9623..1215876 100644
--- a/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultApplicationResolver.java
+++ b/sp-server-impl/src/main/java/net/shibboleth/sp/impl/DefaultAgentResolver.java
@@ -27,27 +27,19 @@ import org.springframework.beans.factory.annotation.Autowired;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.component.IdentifiableComponent;
import net.shibboleth.shared.component.InitializableComponent;
-import net.shibboleth.shared.logic.Constraint;
-import net.shibboleth.shared.primitive.StringSupport;
import net.shibboleth.shared.resolver.CriteriaSet;
import net.shibboleth.shared.resolver.ResolverException;
import net.shibboleth.shared.spring.config.IdentifiedComponentManager;
import net.shibboleth.sp.Agent;
import net.shibboleth.sp.AgentCriterion;
-import net.shibboleth.sp.Application;
-import net.shibboleth.sp.ApplicationCriterion;
-import net.shibboleth.sp.ApplicationResolver;
+import net.shibboleth.sp.AgentResolver;
/**
- * Default implementation of {@link ApplicationResolver}.
+ * Default implementation of {@link AgentResolver}.
*/
-public class DefaultApplicationResolver extends IdentifiedComponentManager<Agent>
- implements ApplicationResolver, InitializableComponent, IdentifiableComponent {
-
- /** Identifier. */
- @Nullable String id;
+public class DefaultAgentResolver extends IdentifiedComponentManager<Agent>
+ implements AgentResolver, InitializableComponent {
/** Tracks init state. */
private boolean initialized;
@@ -61,22 +53,10 @@ public class DefaultApplicationResolver extends IdentifiedComponentManager<Agent
* @param agents agents to autowire into resolver
*/
@Autowired
- public DefaultApplicationResolver(@Nullable final Collection<Agent> agents) {
+ public DefaultAgentResolver(@Nullable final Collection<Agent> agents) {
super(agents);
}
-
- /** {@inheritDoc} */
- @Nullable public String getId() {
- return id;
- }
-
- /** {@inheritDoc} */
- public void setId(@Nonnull final String componentId) {
- if (!initialized) {
- id = Constraint.isNotNull(StringSupport.trimOrNull(componentId), "ID cannot be null or empty");
- }
- }
-
+
/** {@inheritDoc} */
public void initialize() throws ComponentInitializationException {
@@ -95,18 +75,12 @@ public class DefaultApplicationResolver extends IdentifiedComponentManager<Agent
}
/** {@inheritDoc} */
- @Nullable public Application resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+ @Nullable public Agent resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
if (criteria != null) {
final AgentCriterion c_agent = criteria.get(AgentCriterion.class);
if (c_agent != null) {
- final Agent agent = agentMap.get(c_agent.getId());
- if (agent != null) {
- final ApplicationCriterion c_app = criteria.get(ApplicationCriterion.class);
- if (c_app != null) {
- return agent.getApplication(c_app.getId());
- }
- }
+ return agentMap.get(c_agent.getId());
}
}
@@ -114,10 +88,10 @@ public class DefaultApplicationResolver extends IdentifiedComponentManager<Agent
}
/** {@inheritDoc} */
- @Nonnull public Iterable<Application> resolve(@Nullable final CriteriaSet criteria) throws ResolverException {
+ @Nonnull public Iterable<Agent> resolve(@Nullable final CriteriaSet criteria) throws ResolverException {
- final Application app = resolveSingle(criteria);
- return app != null ? CollectionSupport.singletonList(app) : CollectionSupport.emptyList();
+ final Agent agent = resolveSingle(criteria);
+ return agent != null ? CollectionSupport.singletonList(agent) : CollectionSupport.emptyList();
}
}
\ No newline at end of file
diff --git a/sp-server-impl/src/test/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContextTest.java b/sp-server-impl/src/test/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContextTest.java
new file mode 100644
index 0000000..dd9c37b
--- /dev/null
+++ b/sp-server-impl/src/test/java/net/shibboleth/sp/authn/impl/InitializeAgentRequestContextTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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 net.shibboleth.sp.authn.impl;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.springframework.webflow.execution.Event;
+import org.springframework.webflow.execution.RequestContext;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.authn.AuthnEventIds;
+import net.shibboleth.idp.authn.context.AuthenticationContext;
+import net.shibboleth.idp.authn.context.UsernamePasswordContext;
+import net.shibboleth.idp.profile.context.navigate.WebflowRequestContextProfileRequestContextLookup;
+import net.shibboleth.idp.profile.testing.ActionTestingSupport;
+import net.shibboleth.idp.profile.testing.RequestContextBuilder;
+import net.shibboleth.shared.component.ComponentInitializationException;
+import net.shibboleth.sp.context.AgentRequestContext;
+import net.shibboleth.sp.impl.BasicAgent;
+import net.shibboleth.sp.testing.MockAgentResolver;
+
+/**
+ * Unit test for {@link InitializeAgentRequestContext} action.
+ */
+ at SuppressWarnings("javadoc")
+public class InitializeAgentRequestContextTest {
+
+ private RequestContext src;
+ private ProfileRequestContext prc;
+ private BasicAgent agent;
+ private InitializeAgentRequestContext action;
+
+ @BeforeMethod
+ public void setUp() throws ComponentInitializationException {
+ src = new RequestContextBuilder().buildRequestContext();
+ prc = new WebflowRequestContextProfileRequestContextLookup().apply(src);
+ prc.ensureSubcontext(AuthenticationContext.class);
+
+ agent = new BasicAgent();
+ agent.setId("foo");
+ agent.initialize();
+
+ action = new InitializeAgentRequestContext();
+ action.setAgentResolver(MockAgentResolver.getMockResolverService(agent));
+ action.initialize();
+ }
+
+ @Test
+ public void testNoUsername() {
+
+ // No context.
+
+ Event event = action.execute(src);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
+
+ // Empty context.
+ prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(UsernamePasswordContext.class);
+ event = action.execute(src);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
+ }
+
+ @Test
+ public void testNoAgent() {
+ final UsernamePasswordContext upCtx =
+ prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(UsernamePasswordContext.class);
+ upCtx.setUsername("bogus");
+
+ final Event event = action.execute(src);
+ ActionTestingSupport.assertEvent(event, AuthnEventIds.UNKNOWN_USERNAME);
+ }
+
+ @Test
+ public void testSuccess() {
+ final UsernamePasswordContext upCtx =
+ prc.ensureSubcontext(AuthenticationContext.class).ensureSubcontext(UsernamePasswordContext.class);
+ upCtx.setUsername("foo");
+
+ final Event event = action.execute(src);
+ ActionTestingSupport.assertProceedEvent(event);
+
+ final AgentRequestContext agentCtx = prc.getSubcontext(AgentRequestContext.class);
+ assert agentCtx != null;
+ Assert.assertEquals(agent, agentCtx.getAgent());
+ }
+}
\ No newline at end of file
diff --git a/sp-testing/src/main/java/net/shibboleth/sp/testing/MockAgentResolver.java b/sp-testing/src/main/java/net/shibboleth/sp/testing/MockAgentResolver.java
new file mode 100644
index 0000000..1a1a792
--- /dev/null
+++ b/sp-testing/src/main/java/net/shibboleth/sp/testing/MockAgentResolver.java
@@ -0,0 +1,74 @@
+/*
+ * 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 net.shibboleth.sp.testing;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.ResolverException;
+import net.shibboleth.shared.service.ReloadableService;
+import net.shibboleth.shared.testing.MockReloadableService;
+import net.shibboleth.shared.testing.MockResolver;
+import net.shibboleth.sp.Agent;
+import net.shibboleth.sp.AgentCriterion;
+import net.shibboleth.sp.AgentResolver;
+
+/**
+ * Mock {@link AgentResolver} for tests.
+ */
+public class MockAgentResolver extends MockResolver<Agent> implements AgentResolver {
+
+ /** Agent to return. */
+ private final Agent agent;
+
+ /**
+ * Constructor.
+ *
+ * @param a agent to return if a match
+ */
+ public MockAgentResolver(@Nonnull final Agent a) {
+ agent = Constraint.isNotNull(a, "Agent cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Nullable public Agent resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+ super.resolveSingle(criteria);
+
+ final AgentCriterion agentCrit = criteria != null ? criteria.get(AgentCriterion.class) : null;
+ if (agentCrit == null) {
+ throw new ResolverException("No AgentCriterion provided.");
+ }
+
+ if (agentCrit.getId().equals(agent.getId())) {
+ return agent;
+ }
+
+ return null;
+ }
+
+ /**
+ * Wrap a new instance of the mock class in a mocked reloadable service.
+ *
+ * @param a agent to return if a match
+ *
+ * @return mock service
+ */
+ @Nonnull static public ReloadableService<AgentResolver> getMockResolverService(@Nonnull final Agent a) {
+ return new MockReloadableService<>(new MockAgentResolver(a));
+ }
+
+}
\ No newline at end of file
diff --git a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java b/sp-testing/src/main/java/net/shibboleth/sp/testing/package-info.java
similarity index 87%
rename from sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
rename to sp-testing/src/main/java/net/shibboleth/sp/testing/package-info.java
index 61ef139..926f92d 100644
--- a/sp-server-api/src/main/java/net/shibboleth/sp/config/package-info.java
+++ b/sp-testing/src/main/java/net/shibboleth/sp/testing/package-info.java
@@ -13,6 +13,6 @@
*/
/**
- * Core configuration interfaces and classes.
+ * Shared SP testing classes.
*/
-package net.shibboleth.sp.config;
\ No newline at end of file
+package net.shibboleth.sp.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