use the new session manager interface
[java-idp.git] / tests / edu / internet2 / middleware / shibboleth / aa / attrresolv / ResolverTests.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.aa.attrresolv;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.net.MalformedURLException;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27
28 import junit.framework.TestCase;
29
30 import org.apache.log4j.BasicConfigurator;
31 import org.apache.log4j.Level;
32 import org.apache.log4j.Logger;
33 import org.opensaml.SAMLException;
34
35 import edu.internet2.middleware.shibboleth.aa.AAAttribute;
36 import edu.internet2.middleware.shibboleth.aa.attrresolv.provider.ScopedStringValueHandler;
37 import edu.internet2.middleware.shibboleth.common.LocalPrincipal;
38
39 /**
40  * Validation suite for the <code>AttributeResolver</code>.
41  * 
42  * @author Walter Hoehn(wassa@columbia.edu)
43  * @author Vishal Goenka
44  */
45
46 public class ResolverTests extends TestCase {
47
48         // Simple explanatory booleans, which are helpful when passed in functions as compared to true/false
49         private static final boolean DO_SORT = true;
50         private static final boolean DO_NOT_SORT = false;
51
52         public ResolverTests(String name) {
53
54                 super(name);
55                 BasicConfigurator.resetConfiguration();
56                 BasicConfigurator.configure();
57                 Logger.getRootLogger().setLevel(Level.OFF);
58         }
59
60         public static void main(String[] args) {
61
62                 junit.textui.TestRunner.run(ResolverTests.class);
63                 BasicConfigurator.configure();
64                 Logger.getRootLogger().setLevel(Level.OFF);
65         }
66
67         /**
68          * @see junit.framework.TestCase#setUp()
69          */
70         protected void setUp() throws Exception {
71
72                 super.setUp();
73         }
74
75         public void testBasic() {
76
77                 try {
78                         File file = new File("data/resolver1.xml");
79                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
80
81                         Map<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
82                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonNickName");
83                         inputAttributes.put(one.getName(), one);
84                         AAAttribute two = new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement");
85                         inputAttributes.put(two.getName(), two);
86
87                         Map<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
88                         AAAttribute three = new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement",
89                                         new Object[]{"urn:mace:example.edu:exampleEntitlement"});
90                         outputAttributes.put(three.getName(), three);
91
92                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
93
94                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
95
96                 } catch (AttributeResolverException e) {
97                         fail("Couldn't load attribute resolver: " + e.getMessage());
98                 } catch (MalformedURLException e) {
99                         fail("Error in test specification: " + e.getMessage());
100                 } catch (SAMLException e) {
101                         fail("Error creating SAML Attribute: " + e.getMessage());
102                 }
103         }
104
105         public void testSmartScoping() {
106
107                 try {
108
109                         File file = new File("data/resolver2.xml");
110                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
111
112                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
113                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName");
114                         inputAttributes.put(one.getName(), one);
115                         AAAttribute two = new AAAttribute("foo");
116                         inputAttributes.put(two.getName(), two);
117
118                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
119                         // Attribute should have scope appended to connector output
120                         AAAttribute three = new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName",
121                                         new Object[]{"mytestuser@example.edu"}, new ScopedStringValueHandler("example.edu"));
122                         outputAttributes.put(three.getName(), three);
123                         // Attribute should retain scope from connector output
124                         AAAttribute four = new AAAttribute("foo", new Object[]{"bar@example.com"}, new ScopedStringValueHandler(
125                                         "example.edu"));
126                         outputAttributes.put(four.getName(), four);
127
128                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
129                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
130
131                 } catch (AttributeResolverException e) {
132                         fail("Couldn't load attribute resolver: " + e.getMessage());
133                 } catch (MalformedURLException e) {
134                         fail("Error in test specification: " + e.getMessage());
135                 } catch (SAMLException e) {
136                         fail("Error creating SAML Attribute: " + e.getMessage());
137                 }
138         }
139
140         public void testExceptionForNoPlugIns() {
141
142                 try {
143                         File file = new File("data/resolver3.xml");
144                         new AttributeResolver(file.toURL().toString());
145
146                         fail("Attribute Resolver loaded even when no PlugIns were configured.");
147                 } catch (AttributeResolverException e) {
148                         // This exception should be thrown, ignoring
149                 } catch (MalformedURLException e) {
150                         fail("Error in test specification: " + e.getMessage());
151                 }
152         }
153
154         public void testExceptionForNoValidPlugIns() {
155
156                 try {
157                         File file = new File("data/resolver4.xml");
158                         new AttributeResolver(file.toURL().toString());
159                         fail("Attribute Resolver loaded even when no PlugIns were successfully registered.");
160                 } catch (AttributeResolverException e) {
161                         // This exception should be thrown, ignoring
162                 } catch (MalformedURLException e) {
163                         fail("Error in test specification: " + e.getMessage());
164                 }
165         }
166
167         public void testFailToLoadCircularDependencies() {
168
169                 try {
170                         File file = new File("data/resolver5.xml");
171                         new AttributeResolver(file.toURL().toString());
172                         fail("Attribute Resolver loaded even when no only PlugIns with circular dependencies were configured.");
173                 } catch (AttributeResolverException e) {
174                         // This exception should be thrown, ignoring
175                 } catch (MalformedURLException e) {
176                         fail("Error in test specification: " + e.getMessage());
177                 }
178         }
179
180         public void testFailToLoadCircularDependenciesDeeper() {
181
182                 try {
183                         File file = new File("data/resolver6.xml");
184                         new AttributeResolver(file.toURL().toString());
185                         fail("Attribute Resolver loaded even when no only PlugIns with circular dependencies were configured.");
186                 } catch (AttributeResolverException e) {
187                         // This exception should be thrown, ignoring
188                 } catch (MalformedURLException e) {
189                         fail("Error in test specification: " + e.getMessage());
190                 }
191         }
192
193         public void testSourceNameMapping() {
194
195                 try {
196                         File file = new File("data/resolver7.xml");
197                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
198
199                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
200
201                         AAAttribute one = new AAAttribute("myAffiliation");
202                         inputAttributes.put(one.getName(), one);
203
204                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
205                         AAAttribute two = new AAAttribute("myAffiliation", new Object[]{"member"});
206                         outputAttributes.put(two.getName(), two);
207
208                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
209                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
210
211                 } catch (AttributeResolverException e) {
212                         fail("Couldn't load attribute resolver: " + e.getMessage());
213                 } catch (MalformedURLException e) {
214                         fail("Error in test specification: " + e.getMessage());
215                 } catch (SAMLException e) {
216                         fail("Error creating SAML Attribute: " + e.getMessage());
217                 }
218         }
219
220         public void testMultipleDataConnectors() {
221
222                 try {
223                         File file = new File("data/resolver8.xml");
224                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
225
226                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
227                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName");
228                         inputAttributes.put(one.getName(), one);
229                         AAAttribute two = new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation");
230                         inputAttributes.put(two.getName(), two);
231                         AAAttribute three = new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement");
232                         inputAttributes.put(three.getName(), three);
233
234                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
235                         AAAttribute four = new AAAttribute("urn:mace:dir:attribute-def:eduPersonPrincipalName",
236                                         new Object[]{"mytestuser@example.edu"}, new ScopedStringValueHandler("example.edu"));
237                         outputAttributes.put(four.getName(), four);
238                         AAAttribute five = new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation",
239                                         new Object[]{"member"});
240                         outputAttributes.put(five.getName(), five);
241                         AAAttribute six = new AAAttribute("urn:mace:dir:attribute-def:eduPersonEntitlement",
242                                         new Object[]{"urn:mace:example.edu:exampleEntitlement"});
243                         outputAttributes.put(six.getName(), six);
244
245                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
246
247                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
248
249                 } catch (AttributeResolverException e) {
250                         fail("Couldn't load attribute resolver: " + e.getMessage());
251                 } catch (MalformedURLException e) {
252                         fail("Error in test specification: " + e.getMessage());
253                 } catch (SAMLException e) {
254                         fail("Error creating SAML Attribute: " + e.getMessage());
255                 }
256         }
257
258         public void testAttributeDependency() {
259
260                 try {
261                         File file = new File("data/resolver9.xml");
262                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
263
264                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
265                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation");
266                         inputAttributes.put(one.getName(), one);
267
268                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
269                         AAAttribute two = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation",
270                                         new Object[]{"member@example.edu"}, new ScopedStringValueHandler("example.edu"));
271                         outputAttributes.put(two.getName(), two);
272
273                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
274
275                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
276
277                 } catch (AttributeResolverException e) {
278                         fail("Couldn't load attribute resolver: " + e.getMessage());
279                 } catch (MalformedURLException e) {
280                         fail("Error in test specification: " + e.getMessage());
281                 } catch (SAMLException e) {
282                         fail("Error creating SAML Attribute: " + e.getMessage());
283                 }
284         }
285
286         public void testMisLabeledDataConnector() {
287
288                 try {
289                         File file = new File("data/resolver11.xml");
290                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
291
292                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
293                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation");
294                         inputAttributes.put(one.getName(), one);
295
296                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
297
298                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
299
300                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
301
302                 } catch (AttributeResolverException e) {
303                         fail("Couldn't load attribute resolver: " + e.getMessage());
304                 } catch (MalformedURLException e) {
305                         fail("Error in test specification: " + e.getMessage());
306                 } catch (SAMLException e) {
307                         fail("Error creating SAML Attribute: " + e.getMessage());
308                 }
309         }
310
311         public void testMisLabeledAttributeDefinition() {
312
313                 try {
314                         File file = new File("data/resolver10.xml");
315                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
316
317                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
318                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation");
319                         inputAttributes.put(one.getName(), one);
320
321                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
322
323                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
324
325                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
326                 } catch (ClassCastException e) {
327                         fail("Failed to detect that an Attribute Definition was mislabeled as a Data Connector: " + e.getMessage());
328                 } catch (AttributeResolverException e) {
329                         fail("Couldn't load attribute resolver: " + e.getMessage());
330                 } catch (MalformedURLException e) {
331                         fail("Error in test specification: " + e.getMessage());
332                 } catch (SAMLException e) {
333                         fail("Error creating SAML Attribute: " + e.getMessage());
334                 }
335         }
336
337         public void testMultiLevelAttributeDependency() {
338
339                 try {
340                         File file = new File("data/resolver12.xml");
341                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
342
343                         HashMap<String, ResolverAttribute> inputAttributes = new HashMap<String, ResolverAttribute>();
344
345                         AAAttribute one = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation");
346                         inputAttributes.put(one.getName(), one);
347                         AAAttribute two = new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation");
348                         inputAttributes.put(two.getName(), two);
349                         AAAttribute three = new AAAttribute("urn:mace:shibboleth:test:eduPersonAffiliation");
350                         inputAttributes.put(three.getName(), three);
351
352                         HashMap<String, ResolverAttribute> outputAttributes = new HashMap<String, ResolverAttribute>();
353                         AAAttribute four = new AAAttribute("urn:mace:dir:attribute-def:eduPersonScopedAffiliation",
354                                         new Object[]{"member@example.edu"}, new ScopedStringValueHandler("example.edu"));
355                         outputAttributes.put(four.getName(), four);
356                         AAAttribute five = new AAAttribute("urn:mace:dir:attribute-def:eduPersonAffiliation",
357                                         new Object[]{"member"});
358                         outputAttributes.put(five.getName(), five);
359                         AAAttribute six = new AAAttribute("urn:mace:shibboleth:test:eduPersonAffiliation", new Object[]{"member"});
360                         outputAttributes.put(six.getName(), six);
361
362                         ar.resolveAttributes(new LocalPrincipal("mytestuser"), "shar.example.edu", null, inputAttributes);
363
364                         assertEquals("Attribute Resolver returned unexpected attribute set.", inputAttributes, outputAttributes);
365
366                 } catch (AttributeResolverException e) {
367                         fail("Couldn't load attribute resolver: " + e.getMessage());
368                 } catch (MalformedURLException e) {
369                         fail("Error in test specification: " + e.getMessage());
370                 } catch (SAMLException e) {
371                         fail("Error creating SAML Attribute: " + e.getMessage());
372                 }
373         }
374
375         /**
376          * This method is reused by several tests that use different XML files as test data.
377          * 
378          * @param resolverFile
379          *            filename of a file containing data in the same format as resolver.xml.
380          * @param attributeFile
381          *            filename of a file containing output of the attribute resolution. The input file for attribute
382          *            resolution is specified in the resolverFile itself
383          * @param principal
384          *            name of the principal on whose behalf the resolution is done
385          * @param requester
386          *            the Shibboleth Target SHAR that is requesting the attribute resolution
387          */
388
389         private void simpleAttributeResolution(String resolverFile, String attributeFile, String principal,
390                         String requester, boolean sort) {
391
392                 try {
393                         // Create the attribute resolver
394                         File file = new File(resolverFile);
395                         AttributeResolver ar = new AttributeResolver(file.toURL().toString());
396
397                         // Create the output attributes file
398                         AttributesFile attrFile = new AttributesFile(attributeFile);
399
400                         // Read only the attribute names from the output file. The values are set by the resolver
401                         Map<String, AAAttribute> attrsToBeResolved = attrFile.getResolverAttributes(false);
402                         ar.resolveAttributes(new LocalPrincipal(principal), requester, null, attrsToBeResolved);
403
404                         // Read the attribute names and values from the output file
405                         Map<String, AAAttribute> expectedAttributes = attrFile.getResolverAttributes(true);
406
407                         if (sort) {
408                                 sort(attrsToBeResolved);
409                                 sort(expectedAttributes);
410                         }
411                         // Ensure that the values set by the resolver are the same as the ones outlined in the output file
412                         assertEquals("Attribute Resolver returned unexpected attribute set.", expectedAttributes, attrsToBeResolved);
413                 } catch (AttributeResolverException e) {
414                         fail("Couldn't load attribute resolver: " + e.getMessage());
415                 } catch (MalformedURLException e) {
416                         fail("Error in test specification: " + e.getMessage());
417                 } catch (IOException e) {
418                         fail("Error in test data: " + e.getMessage());
419                 } catch (SAMLException e) {
420                         fail("Error creating SAML attribute: " + e.getMessage());
421                 }
422         }
423
424         public void testAttrDef_RegEx_DN_CN_UID() {
425
426                 simpleAttributeResolution("data/attr-regex.resolver.1.xml", "data/attr-regex.output.1", "RegExTestUser",
427                                 "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
428         }
429
430         public void testAttrDef_Mapped_PdsRole_EduPersonAffiliation() {
431
432                 simpleAttributeResolution("data/attr-mapped.resolver.1.xml", "data/attr-mapped.output.1", "MappedTestUser",
433                                 "urn::test:luminis::sungardsct::com", DO_SORT);
434         }
435
436         public void testAttrDef_Mapped_Role_EduPersonEntitlement() {
437
438                 simpleAttributeResolution("data/attr-mapped.resolver.2.xml", "data/attr-mapped.output.2", "MappedTestUser",
439                                 "urn::test:luminis::sungardsct::com", DO_SORT);
440         }
441
442         public void testAttrDef_Formatted_DateOfBirth() {
443
444                 simpleAttributeResolution("data/attr-format.resolver.1.xml", "data/attr-format.output.1",
445                                 "FormattedDateTestUser", "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
446         }
447
448         public void testAttrDef_Formatted_Choice_GPA_Distinction() {
449
450                 simpleAttributeResolution("data/attr-format.resolver.2.xml", "data/attr-format.output.2", "FormattedTestUser",
451                                 "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
452         }
453
454         public void testAttrDef_Composite_LabeledURI() {
455
456                 simpleAttributeResolution("data/attr-composite.resolver.1.xml", "data/attr-composite.output.1",
457                                 "CompositeTestUser", "urn::test:luminis::sungardsct::com", DO_NOT_SORT);
458         }
459
460         // Failing Test cases
461         // How to test that improperly configured definitions will fail to load. Can we check for the specific error?
462         // 
463         /**
464          * 1. RegEx - Custom Value Handler (reverses the characters) can be used 2. Mapped - Custom Value Handler (reverses
465          * the characters) can be used 3. Formatted - Custom Value Handler (reverses the characters) can be used 4.
466          * Composite - Custom Value Handler (reverses the characters) can be used - unordered values should fail - Behavior
467          * with unequal number of values
468          */
469
470         /**
471          * Sort the attribute values in the AAAttribute so that equals comparison works as intended
472          */
473
474         private void sort(Map<String, AAAttribute> attrSet) {
475
476                 for (Iterator<AAAttribute> iter = attrSet.values().iterator(); iter.hasNext();) {
477                         ResolverAttribute attr = iter.next();
478                         if (attr instanceof AAAttribute) {
479                                 ArrayList values = new ArrayList();
480                                 for (Iterator valuesIterator = attr.getValues(); valuesIterator.hasNext();) {
481                                         values.add(valuesIterator.next());
482                                 }
483                                 Object[] sortedValues = values.toArray();
484                                 Arrays.sort(sortedValues);
485
486                                 ((AAAttribute) attr).setValues(sortedValues);
487                         }
488                 }
489         }
490
491 }