Add MockIdp and test case
[java-idp.git] / tests / edu / internet2 / middleware / shibboleth / integration / FileAssertionTest.java
1 /*
2  * Copyright [2005] [University Corporation for Advanced Internet Development, Inc.]
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package edu.internet2.middleware.shibboleth.integration;
18
19 import java.io.FileNotFoundException;
20 import java.io.IOException;
21 import java.security.KeyStoreException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.cert.CertificateException;
24 import java.util.Date;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.Map;
28
29 import javax.naming.directory.Attributes;
30 import javax.naming.directory.BasicAttribute;
31 import javax.servlet.http.HttpServletRequest;
32
33 import junit.framework.TestCase;
34
35 import org.apache.commons.codec.binary.Base64;
36 import org.apache.log4j.Level;
37 import org.opensaml.SAMLException;
38 import org.opensaml.SAMLResponse;
39
40 import edu.internet2.middleware.shibboleth.idp.provider.ShibbolethV1SSOHandler;
41 import edu.internet2.middleware.shibboleth.resource.AuthenticationFilter;
42 import edu.internet2.middleware.shibboleth.resource.FilterUtil;
43 import edu.internet2.middleware.shibboleth.resource.FilterSupport.NewSessionData;
44 import edu.internet2.middleware.shibboleth.runner.MadSignertest;
45 import edu.internet2.middleware.shibboleth.runner.ShibbolethRunner;
46 import edu.internet2.middleware.shibboleth.runner.MadSignertest.MockIdp;
47 import edu.internet2.middleware.shibboleth.runner.ShibbolethRunner.IdpTestContext;
48 import edu.internet2.middleware.shibboleth.serviceprovider.AssertionConsumerServlet;
49 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderConfig;
50 import edu.internet2.middleware.shibboleth.serviceprovider.ServiceProviderContext;
51 import edu.internet2.middleware.shibboleth.serviceprovider.Session;
52
53 /**
54  * A JUnit test case that exercises the IdP, SP, and Filter
55  * @author Howard Gilbert
56  */
57 public class FileAssertionTest extends TestCase {
58     
59     // Create some constants, both as parameters and to test responses
60     private static final String GIVENNAME = "Bozo";
61     public static final String SURNAME = "Clown";
62     private static final String TITLE = "clown";
63     public static final String AFFILIATION = "member";
64     public static final String SP_ENTITY = "https://sp.example.org/shibboleth";
65     public static final String POST_SHIRE = "https://sp.example.org/shibboleth-sp/Shibboleth.sso/SAML/POST";
66     public static final String ARTIFACT_SHIRE = "https://sp.example.org/shibboleth-sp/Shibboleth.sso/SAML/Artifact";
67     public static final String TARGET = "https://nonsense";
68     public static final String NETID = "BozoTClown";
69     public static final String APPLICATIONID = "default";
70     
71     ShibbolethRunner runner;
72     ShibbolethRunner.SPTestContext consumer;
73     ShibbolethRunner.AuthenticationFilterContext filter;
74     private NewSessionData newSessionData = new NewSessionData();
75     ServiceProviderContext context;
76     ServiceProviderConfig config;
77     
78     
79     /**
80      * TestCase setUp
81      * 
82      * <p>There is no IdP or SSO in this test. The IdP function
83      * is performed from assertion files.</p>
84      */
85     protected void setUp() throws Exception {
86         super.setUp();
87
88         // Static call to set Log4J appenders and levels
89         ShibbolethRunner.loglevel = Level.DEBUG;
90         ShibbolethRunner.setupLogging();
91         
92         // Create the overall testing framework
93         runner = new ShibbolethRunner();
94         
95         
96         // Initialize the SP with the default config file.
97         runner.setSpConfigFileName("/basicSpHome/spconfig.xml"); 
98         
99         // Use one of two forms to initialize the SP
100         // Only calling AssertionConsumerServlet.createSessionFromData
101             //runner.initializeSP(); 
102         // Using either MockRunner or direct call to SP
103             consumer = ShibbolethRunner.consumer = runner.new SPTestContext();
104         
105         context=ServiceProviderContext.getInstance();
106         config = context.getServiceProviderConfig();
107         
108         // Initialize the Filter and create its separate
109         // Mockrunner simulated context. 
110         filter= runner.getFilter();
111             // Note: If you are going to change the Filter init-param
112             // values, do it here before calling setUp()
113         filter.setUp();
114   
115         newSessionData.applicationId=APPLICATIONID;
116         newSessionData.providerId=SP_ENTITY;
117         
118     }
119     
120     /**
121      * Test the Post Profile, Attribute Push from an XML Assertion file.
122      * 
123      * <p>Read an AttributePush assertion in from a file, resign it.
124      * Call AssertionConsumerServlet directly, then Run Filter</p>
125      */
126     public void testFileAttributePush() throws Exception {
127         
128         // Setup a signer with the Example.org keystore
129         MadSignertest signer = new MadSignertest("src/conf/idp-example.jks","exampleorg");
130         
131         // Read in and resign a test SAML Response file.
132         SAMLResponse samlresponse = 
133             signer.signResponseFile("data/AttributePushAssertion.xml", 
134                     "tomcat");
135         
136         // Now feed the SAMLResponse into the AssertionConsumer
137         String bin64assertion = new String(samlresponse.toBase64());
138         newSessionData.SAMLResponse = bin64assertion; 
139         
140         // End of the Assertion-File part of the test, the rest is
141         // the same as with a real SSO.
142         
143         newSessionData.target=TARGET;
144         newSessionData.handlerURL=POST_SHIRE;
145         
146         // Create the session, extract pushed Attributes 
147         String sessionId = AssertionConsumerServlet.createSessionFromData(newSessionData);
148         
149         // Now get what was created in case you want to test it.
150         Session session = context.getSessionManager().findSession(sessionId, APPLICATIONID);
151         checkSession(session);
152         
153         // Pass the SessionId to the Filter, let it fetch the attributes
154         filter.resetRequest("test.txt");
155         filter.testModule.addRequestParameter(AuthenticationFilter.SESSIONPARM, sessionId);
156         filter.request.setMethod("GET");
157         filter.testModule.doFilter();
158         
159         checkFilter();
160     }
161     
162     /**
163      * Verify correct operation of Filter and wrapped Request object,
164      * including attributes and headers.
165      */
166     private void checkFilter() {
167         // Get the Request Wrapper object created by the Filter
168         HttpServletRequest filteredRequest = 
169             (HttpServletRequest) filter.testModule.getFilteredRequest();
170         
171         assertEquals(NETID,filteredRequest.getRemoteUser());
172         assertEquals(NETID,filteredRequest.getHeader("REMOTE_USER"));
173         assertEquals(SURNAME,filteredRequest.getHeader("Shib-Person-surname"));
174         assertEquals(GIVENNAME,filteredRequest.getHeader("Shib-InetOrgPerson-givenName"));
175         assertEquals(TITLE,filteredRequest.getHeader("Shib-OrgPerson-title"));
176         
177         Map attributes = (Map) filteredRequest.getAttribute(AuthenticationFilter.SHIB_ATTRIBUTES_PREFIX);
178         Iterator iterator = attributes.entrySet().iterator();
179         while (iterator.hasNext()) {
180             Map.Entry entry = (Map.Entry) iterator.next();
181             String key = (String) entry.getKey();
182             String value = (String) entry.getValue();
183             System.out.println(key+" : "+value);
184         }
185         
186         
187         Enumeration headerNames = filteredRequest.getHeaderNames();
188         while (headerNames.hasMoreElements()) {
189             String name = (String) headerNames.nextElement();
190             String value = (String) filteredRequest.getHeader(name);
191             System.out.println(name+ " : "+value );
192         }
193     }
194     
195     /**
196      * Add Session object checking here.
197      */
198     private void checkSession(Session session) {
199         assertNotNull(session);
200         assertEquals(APPLICATIONID,session.getApplicationId());
201     }
202     
203     /**
204      * Test Attribute Push using a Mock Idp
205      */
206     public void testMockIdp() throws SAMLException, KeyStoreException, NoSuchAlgorithmException, CertificateException, FileNotFoundException, IOException {
207         
208         
209         // Setup a signer with the Example.org keystore
210         MadSignertest signer = new MadSignertest("src/conf/idp-example.jks","exampleorg");
211         
212         // Now create a MockIdp from it
213         MockIdp mockIdp = signer.new MockIdp();
214         
215         // Tell the MockIdP how to respond to an SSO
216         mockIdp.ssoResponseFile = "data/AttributePushAssertion.xml";
217         
218         // Create an IdpTestContext using this MockIdp
219         IdpTestContext idp = runner.new IdpTestContext(mockIdp);
220         
221         // Set the URL suffix that triggers SSO processing
222         idp.resetRequest("SSO");
223         
224         // Add the WAYF/RM parameters
225         idp.testModule.addRequestParameter("target", TARGET);
226         idp.testModule.addRequestParameter("shire",POST_SHIRE);
227         idp.testModule.addRequestParameter("providerId", SP_ENTITY);
228         
229         // Add a userid, as if provided by Basic Authentication or a Filter
230         idp.request.setRemoteUser(NETID);
231         
232         // Force Attribute Push
233         ShibbolethV1SSOHandler.pushAttributeDefault=true;
234         
235         // Call the IdP 
236         idp.testModule.doGet();
237         
238         String bin64assertion = (String) idp.request.getAttribute("assertion");
239         String assertion = new String(Base64.decodeBase64(bin64assertion.getBytes()));
240         String handlerURL = (String) idp.request.getAttribute("shire");
241         String targetURL = (String) idp.request.getAttribute("target");
242         
243         // Create the session directly without MockRunner
244         FilterUtil.sessionDataFromRequest(newSessionData,idp.request);
245             // there was no real redirect, so the next two fields are not
246             // in the places that sessionDataFromRequest expects.
247             newSessionData.SAMLResponse = bin64assertion;  
248             newSessionData.target=targetURL;
249         newSessionData.handlerURL=handlerURL;
250         
251         // Create the session, extract pushed Attributes 
252         String sessionId = AssertionConsumerServlet.createSessionFromData(newSessionData);
253         
254         // Now get what was created in case you want to test it.
255         Session session = context.getSessionManager().findSession(sessionId, APPLICATIONID);
256         checkSession(session);
257         
258         // Pass the SessionId to the Filter, let it fetch the attributes
259         filter.resetRequest("test.txt");
260         filter.testModule.addRequestParameter(AuthenticationFilter.SESSIONPARM, sessionId);
261         filter.request.setMethod("GET");
262         filter.testModule.doFilter();
263         
264         checkFilter();
265     }
266     
267     
268 }